@asyncapi/generator 2.7.0 → 2.8.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/docs/api.md +33 -0
  3. package/docs/baked-in-templates.md +100 -0
  4. package/docs/configuration-file.md +49 -31
  5. package/docs/template.md +22 -3
  6. package/lib/generator.js +31 -3
  7. package/lib/templates/BakedInTemplatesList.json +20 -0
  8. package/lib/templates/bakedInTemplates.js +53 -0
  9. package/package.json +9 -5
  10. package/test/__mocks__/@npmcli/arborist.js +0 -11
  11. package/test/__mocks__/@npmcli/config.js +0 -3
  12. package/test/__mocks__/fs.extra.js +0 -3
  13. package/test/__mocks__/loglevel.js +0 -3
  14. package/test/__mocks__/resolve-from.js +0 -8
  15. package/test/__mocks__/resolve-pkg.js +0 -8
  16. package/test/__snapshots__/integration.test.js.snap +0 -419
  17. package/test/docs/apiwithref.json +0 -41
  18. package/test/docs/dummy.yml +0 -390
  19. package/test/docs/dummyV3.yml +0 -31
  20. package/test/docs/shared.json +0 -27
  21. package/test/docs/ws.yml +0 -36
  22. package/test/generator.test.js +0 -629
  23. package/test/hooksRegistry.test.js +0 -173
  24. package/test/integration.test.js +0 -203
  25. package/test/parser.test.js +0 -205
  26. package/test/renderer.test.js +0 -62
  27. package/test/templateConfigValidator.test.js +0 -294
  28. package/test/test-project/.yarncr.yml +0 -3
  29. package/test/test-project/README.md +0 -8
  30. package/test/test-project/docker-compose.yml +0 -16
  31. package/test/test-project/package.json +0 -24
  32. package/test/test-project/test-global.test.js +0 -37
  33. package/test/test-project/test-project.test.js +0 -102
  34. package/test/test-project/test-registry.test.js +0 -62
  35. package/test/test-project/test.sh +0 -104
  36. package/test/test-project/verdaccio/config.yaml +0 -22
  37. package/test/test-project/verdaccio/htpasswd +0 -1
  38. package/test/test-templates/nunjucks-template/package-lock.json +0 -4062
  39. package/test/test-templates/nunjucks-template/package.json +0 -21
  40. package/test/test-templates/nunjucks-template/template/test-file.md +0 -5
  41. package/test/test-templates/react-template/.ageneratorrc +0 -33
  42. package/test/test-templates/react-template/package.json +0 -14
  43. package/test/test-templates/react-template/template/conditionalFile.txt +0 -0
  44. package/test/test-templates/react-template/template/conditionalFolder/conditionalFile.txt +0 -0
  45. package/test/test-templates/react-template/template/conditionalFolder2/input.txt +0 -0
  46. package/test/test-templates/react-template/template/models.js +0 -6
  47. package/test/test-templates/react-template/template/test-file.md.js +0 -11
  48. package/test/utils.test.js +0 -129
package/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # @asyncapi/generator
2
2
 
3
+ ## 2.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6550745: This release introduces the concept of [`Baked-in Templates`](https://www.asyncapi.com/docs/tools/generator/baked-in-templates).
8
+
9
+ List of currently available baked-in templates is located in [BakedInTemplatesList.json](https://github.com/asyncapi/generator/blob/master/apps/generator/lib/templates/BakedInTemplatesList.json) file that is dynamically regenerated on each release.
10
+
11
+ ### 🚀 New Experimental Feature: **Baked-in Templates**
12
+
13
+ Baked-in Templates are **official AsyncAPI templates that are developed, versioned, and shipped directly inside the `generator` repository**, and are exposed via the `@asyncapi/generator` library. This approach provides a faster, more consistent, and opinionated way to generate code, SDKs, clients, and more—without relying on external packages.
14
+
15
+ All baked-in templates live under the `packages/templates` directory, follow a strict folder structure for maintainability, and are automatically registered in the generator during build time.
16
+
17
+ ### ⚠️ Important Notes
18
+
19
+ - **Experimental**: Baked-in templates are **not recommended for production use yet**. The number of available templates is currently limited, and we’re actively refining the concept.
20
+ - **We need your feedback**: Try them out with your AsyncAPI documents and share your use cases to help us improve them.
21
+ - **No changes to existing templates**: Your current workflow with external templates remains fully supported and works exactly the same as before. Nothing breaks, nothing changes.
22
+
23
+ ### Benefits
24
+
25
+ - Such templates are versioned together with the generator → no mismatches.
26
+ - Faster template discovery and generation process.
27
+ - Clear naming conventions and metadata, making templates easier to maintain and extend.
28
+
29
+ ### What’s Next
30
+
31
+ - We’ll be gradually expanding template coverage (e.g., docs, configs, SDKs) and stabilizing this feature based on community input before recommending production use.
32
+
33
+ - Dedicated support for such templates will be enabled in AsyncAPI CLI. [The PR](https://github.com/asyncapi/cli/pull/1830) is already opened.
34
+
35
+ ## 2.7.1
36
+
37
+ ### Patch Changes
38
+
39
+ - a51f90e: Release of `generator-react-sdk` as part of the `generator` monorepo.
40
+
41
+ With this release the code from https://github.com/asyncapi/generator-react-sdk is considered to be an archive, and all future development will take place in this repository under `/apps/react-sdk`.
42
+
43
+ - Updated dependencies [a51f90e]
44
+ - @asyncapi/generator-react-sdk@1.1.3
45
+
3
46
  ## 2.7.0
4
47
 
5
48
  ### Minor Changes
package/docs/api.md CHANGED
@@ -4,6 +4,22 @@ weight: 75
4
4
  ---
5
5
 
6
6
  Reference API documentation for AsyncAPI Generator library.
7
+ ## Classes
8
+
9
+ <dl>
10
+ <dt><a href="#Generator">Generator</a></dt>
11
+ <dd></dd>
12
+ </dl>
13
+
14
+ ## Members
15
+
16
+ <dl>
17
+ <dt><a href="#listBakedInTemplates">listBakedInTemplates</a> ⇒ <code>Array.&lt;Object&gt;</code></dt>
18
+ <dd><p>List core templates, optionally filter by type, stack, protocol, or target.
19
+ Use name of returned templates as input for the <code>generate</code> method for template generation. Such core templates code is part of the @asyncapi/generator package.</p>
20
+ </dd>
21
+ </dl>
22
+
7
23
 
8
24
  <a name="Generator"></a>
9
25
 
@@ -494,3 +510,20 @@ const content = await Generator.getTemplateFile('@asyncapi/html-template', 'part
494
510
  const Generator = require('@asyncapi/generator');
495
511
  const content = await Generator.getTemplateFile('@asyncapi/html-template', 'partials/content.html', '~/my-templates');
496
512
  ```
513
+
514
+ <a name="listBakedInTemplates"></a>
515
+
516
+ ## listBakedInTemplates
517
+ List core templates, optionally filter by type, stack, protocol, or target.
518
+ Use name of returned templates as input for the `generate` method for template generation. Such core templates code is part of the @asyncapi/generator package.
519
+
520
+ **Kind**: global variable
521
+ **Returns**: `Array.<Object>` - Array of template objects matching the filter.
522
+ **Params**
523
+
524
+ - [filter] `Object` - Optional filter object.
525
+ - [.type] `string` - Filter by template type (e.g., 'client', 'docs').
526
+ - [.stack] `string` - Filter by stack (e.g., 'quarkus', 'express').
527
+ - [.protocol] `string` - Filter by protocol (e.g., 'websocket', 'http').
528
+ - [.target] `string` - Filter by target language or format (e.g., 'javascript', 'html').
529
+
@@ -0,0 +1,100 @@
1
+ ---
2
+ title: "Baked-in Templates"
3
+ weight: 55
4
+ ---
5
+
6
+ > This is a new concept introduced in generator version 2.8. The number of templates is limited and solution is still in experimental phase. It is not recommended to use them in production. Instead join us to help to improve them with your use cases and your AsyncAPI documents.
7
+
8
+ Baked-in templates are official AsyncAPI templates that are **developed, versioned, and shipped directly inside the `generator` repository and exposed with `@asyncapi/generator` library**.
9
+
10
+ AsyncAPI Generator supports a variety of baked-in template types for generating code, documentation, configs, and SDKs. All templates are managed under the `packages/templates` directory and follow a strict, opinionated directory structure for consistency and ease of maintenance.
11
+
12
+ > List of baked-in templates: https://github.com/asyncapi/generator/blob/master/apps/generator/lib/templates/BakedInTemplatesList.json
13
+
14
+ ## Supported template types
15
+
16
+ Templates are grouped by **type**, which must be one of the following:
17
+
18
+ - `docs` (not yet implemented): Templates that generate documentation
19
+ - `client`: Templates that generate clients
20
+ - `sdk` (not yet implemented): Template that generate full sdk's
21
+ - `config` (not yet implemented): Template that generate configuration files
22
+
23
+ > **Note:**
24
+ > The **directory name is always plural** (e.g., `clients`), but the **type recorded in metadata and package name is singular** (e.g., `client`), except for `docs`.
25
+
26
+ ## Template directory structure
27
+
28
+ ### General structure
29
+
30
+ All template directories must follow this convention:
31
+ ```
32
+ packages/templates/{type}/[protocol]/[target]/[stack]
33
+ ```
34
+
35
+ - `type`: One of `docs`, `clients`, `sdks`, or `configs`.
36
+ - `protocol`: (Only for `clients` and `sdks`) The protocol this template supports, e.g. `websocket`, `http`, `kafka`.
37
+ - `target`: The output language, markup, or format, e.g. `javascript`, `python`, `html`, `yaml`.
38
+ - `stack`: (Optional, for `clients` and `sdks`) Used for technology stack, e.g. `express`, `quarkus`.
39
+
40
+ #### Type-specific rules
41
+
42
+ - **docs/configs**:
43
+ Path must be `type/target` (e.g., `docs/html` or `configs/yaml`).
44
+ - **clients/sdks**:
45
+ Path must be `type/protocol/target` or `type/protocol/target/stack` (e.g., `clients/websocket/javascript`, `sdks/kafka/java/spring`).
46
+
47
+ ### Required files
48
+
49
+ Every template directory **must include**:
50
+ - `.ageneratorrc`: Generator specific configuration, like for example parameters
51
+ - `package.json`: It contains template name. Version information should not be provided as it is versioned together with the generator.
52
+
53
+ ## Metadata and naming conventions
54
+
55
+ Generator build runs a script that normalize metadata for baked-in templates and their naming:
56
+ - Adds/updates metadata in `.ageneratorrc` file. You do not have to maintain it manually.
57
+ - Validates/updates template name in `package.json` file of given template. The name always starts with `core-template-` prefix.
58
+ - Generates JSON file with list of baked in templates and stores the list inside the generator: `apps/generator/lib/templates/BakedInTemplatesList.json`
59
+
60
+ #### Example
61
+
62
+ Example information provided for template stored under `packages/templates/clients/websocket/javascript/express`
63
+
64
+ ```yaml
65
+ # .ageneratorrc
66
+ metadata:
67
+ type: client
68
+ protocol: websocket
69
+ target: javascript
70
+ stack: express
71
+ ```
72
+
73
+ Package name format: `core-template-client-websocket-javascript-express`
74
+
75
+ Resulting entry in `apps/generator/lib/templates/BakedInTemplatesList.json`:
76
+ ```json
77
+ {
78
+ "name": "core-template-client-websocket-javascript-express",
79
+ "type": "client",
80
+ "protocol": "websocket",
81
+ "target": "javascript",
82
+ "stack": "express"
83
+ }
84
+ ```
85
+
86
+ ## How to add a new baked-in template
87
+
88
+ 1. Create the directory in `packages/templates` using the correct structure.
89
+ - For a docs template:
90
+ `packages/templates/docs/html`
91
+ - For a clients template:
92
+ `packages/templates/clients/websocket/rust`
93
+ 1. Add required files:
94
+ - `.ageneratorrc` (do not add `generator` config key as it is not needed)
95
+ - `package.json`
96
+ 1. Run generator's build command: `npm run build`
97
+
98
+ ## Templates exposed through generator
99
+
100
+ Templates that are exposed as part of the generator are transpiled with the `react-sdk` and located in published library under `/lib/templates/bakedInTemplates`. This means that in case of baked-in templates, they are not picked by the generator from `node_modules`. This way the process of generation is faster and more efficient.
@@ -5,14 +5,22 @@ weight: 90
5
5
 
6
6
  You can configure your AsyncAPI Generator template using either a dedicated `.ageneratorrc` YAML file or through the `generator` property in your `package.json` file. Previously, generator configuration had to be defined in the `package.json` file. Now, you can define the configuration in a separate `.ageneratorrc` file. The configuration defined in the `.ageneratorrc` file will override any configuration defined in `package.json`. The generator will first check for the `.ageneratorrc` file in the template's root directory, and if not found, it will look for the generator config in `package.json`.
7
7
 
8
+ > **Note:** The `metadata` object is **required** for all baked-in templates (templates developed and shipped as part of the Generator repository) and is used by the generator’s build system to index, categorize, and load these templates.
9
+ > The `metadata` section is **not used or required** for standalone templates (external npm packages or repositories).
8
10
 
9
- ## Configuration Methods
11
+ ## Configuration methods
10
12
 
11
- ### Option 1: Using `.ageneratorrc` file (Recommended)
13
+ ### Option 1: using `.ageneratorrc` file (Recommended)
12
14
 
13
15
  Create a `.ageneratorrc` file in the root of your template with YAML syntax. This approach keeps your template configuration separate from package metadata:
14
16
 
15
17
  ```yaml
18
+ metadata:
19
+ type: client
20
+ protocol: websocket
21
+ target: javascript
22
+ stack: express
23
+
16
24
  renderer: react
17
25
  apiVersion: v3
18
26
  supportedProtocols:
@@ -64,15 +72,20 @@ hooks:
64
72
  my-custom-hooks-package:
65
73
  - myHook
66
74
  - andAnotherOne
67
-
68
75
  ```
69
76
 
70
- ### Option 2: Using `package.json`
77
+ ### Option 2: using `package.json`
71
78
 
72
79
  Alternatively, you can include your configuration in the `generator` property of your `package.json` file:
73
80
 
74
81
  ```json
75
82
  "generator": {
83
+ "metadata": {
84
+ "type": "client",
85
+ "protocol": "websocket",
86
+ "target": "javascript",
87
+ "stack": "express"
88
+ },
76
89
  "renderer": "react",
77
90
  "apiVersion": "v3",
78
91
  "supportedProtocols": ["amqp", "mqtt"],
@@ -105,7 +118,7 @@ Alternatively, you can include your configuration in the `generator` property of
105
118
  "validation": {
106
119
  "const": "API Support"
107
120
  }
108
- },
121
+ }
109
122
  },
110
123
  "nonRenderableFiles": [
111
124
  "src/api/middlewares/*.*",
@@ -124,37 +137,42 @@ Alternatively, you can include your configuration in the `generator` property of
124
137
 
125
138
  > **Note:** If both `.ageneratorrc` file and the `generator` property in `package.json` exist, the configuration from `.ageneratorrc` will override the `package.json` configuration.
126
139
 
127
- The `generator` property from `package.json` file and must contain a JSON object and the `ageneratorrc` file must contain a YAML object that may have the following information:
128
-
129
-
130
- |Name|Type|Description|
131
- |---|---|---|
132
- |`renderer`| String | Its value can be either `react` or `nunjucks` (default).
133
- |`apiVersion`| String | Determines which **major** version of the [Parser-API](https://github.com/asyncapi/parser-api) the template uses. For example, `v2` for `v2.x.x`. If not specified, the Generator assumes the template is not compatible with the Parser-API so it will use the [Parser-JS v1 API](https://github.com/asyncapi/parser-js/tree/v1.18.1#api-documentation). For templates that need to support AsyncAPI specification v3 make sure to use `v3` [Parser-API](https://github.com/asyncapi/parser-api). If the template uses a version of the Parser-API that is not supported by the Generator, the Generator will throw an error.
134
- |`supportedProtocols`| [String] | A list with all the protocols this template supports.
135
- |`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`.
136
- |`parameters[param].description`| String | A user-friendly description about the parameter.
137
- |`parameters[param].default`| Any | Default value of the parameter if not specified. Shouldn't be used for mandatory `required=true` parameters.
138
- |`parameters[param].required`| Boolean | Whether the parameter is required or not.
140
+ ## Configuration options reference
141
+
142
+ The following table describes all available configuration options for templates.
143
+
144
+ The `generator` property from `package.json` file must contain a JSON object and the `ageneratorrc` file must contain a YAML object that may have the following information:
145
+
146
+ | Name | Type | Description |
147
+ |------|------|-------------|
148
+ | `metadata` | Object | **(Required for baked-in templates)**. Template identification and classification. Contains `type`, `protocol`, `target`, and optional `stack`. See below. |
149
+ | `metadata.type` | String | **Required**. The type of template. Allowed values: `client`, `sdk`, `docs`, `config`. |
150
+ | `metadata.protocol` | String | **Required for `client`/`sdk`**. The protocol this template targets (e.g., `websocket`, `kafka`). Not used for `docs`/`config`. |
151
+ | `metadata.target` | String | **Required**. The output language or format (e.g., `javascript`, `html`, `yaml`). |
152
+ | `metadata.stack` | String | Optional. The stack or framework (e.g., `express`, `quarkus`). Only for `client`/`sdk`. |
153
+ | `renderer` | String | Its value can be either `react` or `nunjucks` (default). |
154
+ | `apiVersion` | String | Determines which **major** version of the [Parser-API](https://github.com/asyncapi/parser-api) the template uses. For example, `v2` for `v2.x.x`. If not specified, the Generator assumes the template is not compatible with the Parser-API so it will use the [Parser-JS v1 API](https://github.com/asyncapi/parser-js/tree/v1.18.1#api-documentation). For templates that need to support AsyncAPI specification v3 make sure to use `v3` [Parser-API](https://github.com/asyncapi/parser-api). If the template uses a version of the Parser-API that is not supported by the Generator, the Generator will throw an error. |
155
+ | `supportedProtocols` | [String] | A list with all the protocols this template supports. |
156
+ | `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`. |
157
+ | `parameters[param].description` | String | A user-friendly description about the parameter. |
158
+ | `parameters[param].default` | Any | Default value of the parameter if not specified. Shouldn't be used for mandatory `required=true` parameters. |
159
+ | `parameters[param].required` | Boolean | Whether the parameter is required or not. |
139
160
  | `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. **Note: It is deprecated and will be removed with future releases. Use `conditionalGeneration` instead.** |
140
161
  | `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 the `server` parameter, you can access server details, for example, `server.protocol`. During validation with `conditionalFiles`, only the server that the template user selected is available in the specification file. For more information about `server` parameter [read about special parameters](#special-parameters). **Note: It is deprecated and will be removed with future releases. Use `conditionalGeneration` instead.** |
141
162
  | `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) for a list of all possible validation keywords. **Note: It is deprecated and will be removed with future releases. Use `conditionalGeneration` instead.** |
142
- |`conditionalGeneration` | Object[String, { subject?: String, parameter?: String, validation: Object }] | An object containing all the file paths or directory names that should be conditionally rendered. Each key represents a file path or directory name and each value must be an object with the keys `subject`, `parameter` and `validation`. You can use either subject or parameter according to the use case. The path should be relative to the `template` directory inside the template. **Note: conditionalGeneration and conditionalFile are mutually exclusive, which means both cannot be configured at the same time in the template**. |
143
- |`conditionalGeneration[filePath/directoryName].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 the `server` parameter, you can access server details like, for example, protocol this way: `server.protocol`. During validation with `conditionalGeneration`, only the server that the template user selected is available in the specification file. For more information about the `server` parameter [read about special parameters](#special-parameters). |
144
- |`conditionalGeneration[filePath/directoryName].parameter`| String | The `parameter` is the name of a custom template parameter passed through `templateParams` that controls whether a specific file or folder should be included in the generated output. You must define a `validation` rule using a JSON Schema fragment to apply the condition. For example, if you define `"parameter": "includeDocs"` with `"validation": { "const": true }`, the corresponding folder (e.g., `docs/`) will only be generated when the user passes `{ includeDocs: true }`. If `includeDocs` is `false`, it will be skipped. |
145
- |`conditionalGeneration[filePath/directoryName].validation`| Object (JSON Schema fragment) | The validation defines the condition under which the file or directory will be generated. It must be a valid JSON Schema fragment that validates the value of the parameter. For example, if you want to include a folder only when includeDocs is true, use "validation": { "const": true }. You can also use more complex validation logic, like "enum": ["yes", "true"] or "type": "string" with a "pattern" constraint. If the parameter fails validation, the file or folder will not be included in the generated output. This allows for powerful and flexible control over template generation based on user input. |
146
- |`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.
147
- |`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).
148
- |`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.
149
- |`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.
150
-
151
- ---
163
+ | `conditionalGeneration` | Object[String, `{ subject?: String, parameter?: String, validation: Object }`] | An object containing all the file paths or directory names that should be conditionally rendered. Each key represents a file path or directory name and each value must be an object with the keys `subject`, `parameter` and `validation`. You can use either subject or parameter according to the use case. The path should be relative to the `template` directory inside the template. **Note: conditionalGeneration and conditionalFile are mutually exclusive, which means both cannot be configured at the same time in the template**. |
164
+ | `conditionalGeneration[filePath/directoryName].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 the `server` parameter, you can access server details like, for example, protocol this way: `server.protocol`. During validation with `conditionalGeneration`, only the server that the template user selected is available in the specification file. For more information about the `server` parameter [read about special parameters](#special-parameters). |
165
+ | `conditionalGeneration[filePath/directoryName].parameter` | String | The `parameter` is the name of a custom template parameter passed through `templateParams` that controls whether a specific file or folder should be included in the generated output. You must define a `validation` rule using a JSON Schema fragment to apply the condition. For example, if you define `"parameter": "includeDocs"` with `"validation": { "const": true }`, the corresponding folder (e.g., `docs/`) will only be generated when the user passes `{ includeDocs: true }`. If `includeDocs` is `false`, it will be skipped. |
166
+ | `conditionalGeneration[filePath/directoryName].validation` | Object (JSON Schema fragment) | The validation defines the condition under which the file or directory will be generated. It must be a valid JSON Schema fragment that validates the value of the parameter. For example, if you want to include a folder only when includeDocs is true, use "validation": `{ "const": true }`. You can also use more complex validation logic, like "enum": ["yes", "true"] or "type": "string" with a "pattern" constraint. If the parameter fails validation, the file or folder will not be included in the generated output. This allows for powerful and flexible control over template generation based on user input. |
167
+ | `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. |
168
+ | `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). |
169
+ | `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. |
170
+ | `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. |
152
171
 
153
172
  ## Special parameters
154
173
 
155
174
  There are some template parameters that have a special meaning:
156
175
 
157
- |Name|Description|
158
- |---|---|
159
- |`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 `conditionalGeneration` 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 `conditionalGeneration` is not going to work if your users do not use this parameter obligatory.
160
-
176
+ | Name | Description |
177
+ |------|-------------|
178
+ | `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 `conditionalGeneration` 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 `conditionalGeneration` is not going to work if your users do not use this parameter obligatory.
package/docs/template.md CHANGED
@@ -5,7 +5,7 @@ weight: 50
5
5
 
6
6
  ## Template
7
7
 
8
- A template is a project that specifies the generation process output by using the AsyncAPI generator and an [AsyncAPI document](asyncapi-document). These files describe the generation results depending on the AsyncAPI document's content.
8
+ A template is a project that specifies the generation process output by using the AsyncAPI Generator (generator) and an [AsyncAPI document](asyncapi-document). These files describe the generation results depending on the AsyncAPI document's content.
9
9
 
10
10
  Examples outputs:
11
11
 
@@ -14,7 +14,26 @@ Examples outputs:
14
14
  - Markdown diagrams
15
15
  - Python and Java applications
16
16
 
17
- A template is an independent Node.js project unrelated to the `generator` repository. AsyncAPI templates are managed, released, and published separately. You can also create templates and manage templates on your own.
17
+ Templates can be developed as standalone project. There is also a set of baked-in core templates that are available in the generator out of the box.
18
+
19
+ ### Baked-in templates
20
+
21
+ > This is a new concept introduced in generator version 2.8. The number of templates is limited and solution is still in experimental phase
22
+
23
+ Baked-in templates are official AsyncAPI templates that are **developed, versioned, and shipped directly inside the `generator` repository and exposed with `@asyncapi/generator` library**. Source code of these templates live in the `packages/templates` directory of the `generator` repository. These templates and are managed alongside the generator’s core source code. Baked-in templates are always available “out of the box” when using the generator. No separate installation or network fetching is required.
24
+
25
+ Baked-in templates benefit from:
26
+ - **Tight integration** with the generator’s features and release cycle.
27
+ - **Instant availability:** They are bundled as part of every release, so you never need to install or fetch them separately.
28
+ - **Unified contributions:** Any improvements or changes to these templates happen through pull requests to the generator repository itself, keeping everything in sync. They share a lot of common parts which makes templates development faster.
29
+
30
+ In contrast, **standalone templates** (described below) are maintained as independent Node.js packages, may live in separate repositories, and can be managed or installed separately from the core generator.
31
+
32
+ Learn more from document [Baked-in Templates](#baked-in-templates).
33
+
34
+ ### Standalone templates
35
+
36
+ A standalone template is an independent Node.js project unrelated to the `generator` repository. AsyncAPI templates are managed, released, and published separately. You can also create templates and manage templates on your own.
18
37
 
19
38
  The generator uses the official [Arborist](https://www.npmjs.com/package/@npmcli/arborist) NPM library. (This means templates do not have to be published to package managers to use them.) Arborist helps the generator fetch the template's source code and use it for the generation process. By default, this library pulls data from the default NPM registry, which is https://registry.npmjs.org. You can also configure the generator to fetch templates that are private or hosted in different NPM registry
20
39
 
@@ -44,7 +63,7 @@ graph LR
44
63
  end
45
64
  ```
46
65
 
47
- ## Generator `templates` list
66
+ ## Standalone templates list
48
67
 
49
68
  AsyncAPI has a list of available templates to enhance your generation process. Templates are stored as repositories on AsyncAPI's official GitHub profile.
50
69
 
package/lib/generator.js CHANGED
@@ -15,6 +15,7 @@ const { configureReact, renderReact, saveRenderedReactContent } = require('./ren
15
15
  const { configureNunjucks, renderNunjucks } = require('./renderer/nunjucks');
16
16
  const { validateTemplateConfig } = require('./templateConfigValidator');
17
17
  const { isGenerationConditionMet } = require('./conditionalGeneration');
18
+ const { listBakedInTemplates, isCoreTemplate, getTemplate } = require('./templates/bakedInTemplates');
18
19
  const {
19
20
  convertMapToObject,
20
21
  isFileSystemPath,
@@ -281,11 +282,26 @@ class Generator {
281
282
  * A promise that resolves to an object containing the name and path of the installed template.
282
283
  */
283
284
  async installAndSetupTemplate() {
284
- const { name: templatePkgName, path: templatePkgPath } = await this.installTemplate(this.install);
285
+ const shouldSkipInstall = isCoreTemplate(this.templateName);
286
+
287
+ let templatePkgName, templatePkgPath;
288
+
289
+ if (shouldSkipInstall) {
290
+ // Use core template info from local registry
291
+ const template = await getTemplate(this.templateName);
292
+ templatePkgName = template.name;
293
+ templatePkgPath = template.path;
294
+ } else {
295
+ // Download and install external template
296
+ const installResult = await this.installTemplate(this.install);
297
+ templatePkgName = installResult.name;
298
+ templatePkgPath = installResult.path;
299
+ }
300
+
285
301
  this.templateDir = templatePkgPath;
286
302
  this.templateName = templatePkgName;
287
303
  this.templateContentDir = path.resolve(this.templateDir, TEMPLATE_CONTENT_DIRNAME);
288
-
304
+
289
305
  await this.loadTemplateConfig();
290
306
 
291
307
  return { templatePkgName, templatePkgPath };
@@ -1138,4 +1154,16 @@ class Generator {
1138
1154
  Generator.DEFAULT_TEMPLATES_DIR = DEFAULT_TEMPLATES_DIR;
1139
1155
  Generator.TRANSPILED_TEMPLATE_LOCATION = TRANSPILED_TEMPLATE_LOCATION;
1140
1156
 
1141
- module.exports = Generator;
1157
+ module.exports = Generator;
1158
+ /**
1159
+ * List core templates, optionally filter by type, stack, protocol, or target.
1160
+ * Use name of returned templates as input for the `generate` method for template generation. Such core templates code is part of the @asyncapi/generator package.
1161
+ *
1162
+ * @param {Object} [filter] - Optional filter object.
1163
+ * @param {string} [filter.type] - Filter by template type (e.g., 'client', 'docs').
1164
+ * @param {string} [filter.stack] - Filter by stack (e.g., 'quarkus', 'express').
1165
+ * @param {string} [filter.protocol] - Filter by protocol (e.g., 'websocket', 'http').
1166
+ * @param {string} [filter.target] - Filter by target language or format (e.g., 'javascript', 'html').
1167
+ * @returns {Array<Object>} Array of template objects matching the filter.
1168
+ */
1169
+ module.exports.listBakedInTemplates = listBakedInTemplates;
@@ -0,0 +1,20 @@
1
+ [
2
+ {
3
+ "name": "core-template-client-websocket-dart",
4
+ "type": "client",
5
+ "protocol": "websocket",
6
+ "target": "dart"
7
+ },
8
+ {
9
+ "name": "core-template-client-websocket-javascript",
10
+ "type": "client",
11
+ "protocol": "websocket",
12
+ "target": "javascript"
13
+ },
14
+ {
15
+ "name": "core-template-client-websocket-python",
16
+ "type": "client",
17
+ "protocol": "websocket",
18
+ "target": "python"
19
+ }
20
+ ]
@@ -0,0 +1,53 @@
1
+ const templates = require('./BakedInTemplatesList.json');
2
+ const path = require('path');
3
+
4
+ const BAKED_IN_TEMPLATES_DIR = path.resolve(__dirname, 'bakedInTemplates');
5
+ /**
6
+ * List core templates, optionally filter by type, stack, protocol, or target.
7
+ * Use name of returned templates as input for the `generate` method for template generation. Such core templates code is part of the @asyncapi/generator package.
8
+ *
9
+ * @param {Object} [filter] - Optional filter object.
10
+ * @param {string} [filter.type] - Filter by template type (e.g., 'client', 'docs').
11
+ * @param {string} [filter.stack] - Filter by stack (e.g., 'quarkus', 'express').
12
+ * @param {string} [filter.protocol] - Filter by protocol (e.g., 'websocket', 'http').
13
+ * @param {string} [filter.target] - Filter by target language or format (e.g., 'javascript', 'html').
14
+ * @returns {Array<Object>} Array of template objects matching the filter.
15
+ */
16
+ module.exports.listBakedInTemplates = (filter) => {
17
+ const { type, stack, protocol, target } = filter || {};
18
+
19
+ return templates.filter(t =>
20
+ (!type || t.type === type) &&
21
+ (!stack || t.stack === stack) &&
22
+ (!protocol || t.protocol === protocol) &&
23
+ (!target || t.target === target)
24
+ );
25
+ };
26
+
27
+ /**
28
+ * Check if a template exists in the core templates list.
29
+ *
30
+ * @param {string} templateName - The name of the template to check.
31
+ * @returns {boolean} True if the template exists, false otherwise.
32
+ */
33
+ module.exports.isCoreTemplate = (templateName) => {
34
+ return templates.some(t => t.name === templateName);
35
+ };
36
+
37
+ /**
38
+ * Retrieve a template by name and validate its path.
39
+ * If the path does not exist, fallback to `node_modules/{templateName}`.
40
+ *
41
+ * @async
42
+ * @param {string} templateName - The name of the template to retrieve.
43
+ * @returns {Promise<{name: string, path: string}|undefined>} An object containing the template's name and path, or undefined if not found.
44
+ */
45
+ module.exports.getTemplate = async (templateName) => {
46
+ const template = templates.find(t => t.name === templateName);
47
+
48
+ const templatePath = template?.path || path.resolve(__dirname, BAKED_IN_TEMPLATES_DIR, template.name);
49
+ return {
50
+ name: template.name,
51
+ path: templatePath
52
+ };
53
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asyncapi/generator",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "The AsyncAPI generator. It can generate documentation, code, anything!",
5
5
  "main": "./lib/generator.js",
6
6
  "bin": {
@@ -13,17 +13,21 @@
13
13
  },
14
14
  "scripts": {
15
15
  "test": "npm run test:unit && npm run test:integration",
16
- "test:unit": "jest --coverage --testPathIgnorePatterns=integration --testPathIgnorePatterns=test-project",
16
+ "test:unit": "jest --coverage --testPathIgnorePatterns=bakedInTemplates --testPathIgnorePatterns=integration --testPathIgnorePatterns=test-project",
17
17
  "test:dev": "npm run test:unit -- --watchAll",
18
18
  "test:integration": "npm run test:cleanup && jest --testPathPattern=integration --modulePathIgnorePatterns='./__mocks__(?!\\/loglevel\\.js$)'",
19
- "test:integration:update": "jest --updateSnapshot --testPathPattern=integration --modulePathIgnorePatterns='./__mocks__(?!\\/loglevel\\.js$)'",
19
+ "test:integration:update": "npm run test:integration -- -u",
20
20
  "test:cleanup": "rimraf \"test/temp\"",
21
21
  "docs": "jsdoc2md --partial docs/jsdoc2md-handlebars/custom-sig-name.hbs docs/jsdoc2md-handlebars/main.hbs docs/jsdoc2md-handlebars/docs.hbs docs/jsdoc2md-handlebars/header.hbs docs/jsdoc2md-handlebars/defaultvalue.hbs docs/jsdoc2md-handlebars/link.hbs docs/jsdoc2md-handlebars/params-table.hbs --files lib/generator.js > docs/api.md",
22
22
  "docker:build": "docker build -t asyncapi/generator:latest .",
23
23
  "lint": "eslint --max-warnings 0 --config ../../.eslintrc --ignore-path ../../.eslintignore .",
24
+ "lint:fix": "npm run lint -- --fix",
24
25
  "generate:readme:toc": "markdown-toc -i README.md",
25
26
  "generate:assets": "npm run docs && npm run generate:readme:toc",
26
- "bump:version": "npm --no-git-tag-version --allow-same-version version $VERSION"
27
+ "bump:version": "npm --no-git-tag-version --allow-same-version version $VERSION",
28
+ "build": "node scripts/build-templates.js",
29
+ "pretest": "npm run build",
30
+ "prepublish": "npm run build"
27
31
  },
28
32
  "preferGlobal": true,
29
33
  "bugs": {
@@ -48,7 +52,7 @@
48
52
  "homepage": "https://github.com/asyncapi/generator",
49
53
  "dependencies": {
50
54
  "@asyncapi/generator-hooks": "*",
51
- "@asyncapi/generator-react-sdk": "^1.1.2",
55
+ "@asyncapi/generator-react-sdk": "*",
52
56
  "@asyncapi/multi-parser": "^2.1.1",
53
57
  "@asyncapi/nunjucks-filters": "*",
54
58
  "@asyncapi/parser": "^3.0.14",
@@ -1,11 +0,0 @@
1
- const arb = jest.genMockFromModule('@npmcli/arborist');
2
-
3
- arb.prototype[Symbol.for('resolvedAdd')] = [{name: 'test'}];
4
-
5
- arb.prototype.reify = jest.fn(async (opt) => {
6
- const childrenMap = new Map();
7
- childrenMap.set('test', {path: './test'});
8
- return { children: childrenMap };
9
- });
10
-
11
- module.exports = arb;
@@ -1,3 +0,0 @@
1
- const npmConfig = jest.genMockFromModule('@npmcli/config');
2
-
3
- module.exports = npmConfig;
@@ -1,3 +0,0 @@
1
- const xfs = jest.genMockFromModule('fs.extra');
2
-
3
- module.exports = xfs;
@@ -1,3 +0,0 @@
1
- const log = jest.genMockFromModule('loglevel');
2
-
3
- module.exports = log;
@@ -1,8 +0,0 @@
1
- let resolveFrom = jest.genMockFromModule('resolve-from');
2
-
3
- resolveFrom.__resolveFromValue = '';
4
- resolveFrom = jest.fn((path) => {
5
- return resolveFrom.__resolveFromValue;
6
- });
7
-
8
- module.exports = resolveFrom;
@@ -1,8 +0,0 @@
1
- let resolvePkg = jest.genMockFromModule('resolve-pkg');
2
-
3
- resolvePkg.__resolvePkgValue = '';
4
- resolvePkg = jest.fn((path) => {
5
- return resolvePkg.__resolvePkgValue;
6
- });
7
-
8
- module.exports = resolvePkg;