Skip to content

Commit e1a418d

Browse files
authored
Merge branch 'master' into docs/rewrite-template-tutorial-v3
2 parents ef3292e + 1689b66 commit e1a418d

File tree

119 files changed

+5429
-283
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+5429
-283
lines changed

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,5 @@ test-results
3939
**/Dockerfile
4040
**/docker-compose*.yml
4141
**/docker-compose*.yaml
42+
!**/template/**/docker-compose*.yml
43+
!**/template/**/docker-compose*.yaml

.github/workflows/scripts/mailchimp/package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Development.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ git clone https://github.com/{your_username}/generator.git
3131
cd generator
3232
```
3333

34-
After cloning the repository, you should setup the fork properly and configure the `remote` repository as described [here](https://github.com/asyncapi/community/blob/master/git-workflow.md)
34+
After cloning the repository, you should setup the fork properly and configure the `remote` repository as described in the [AsyncAPI git workflow guidelines](https://github.com/asyncapi/community/blob/master/docs/010-contribution-guidelines/git-workflow.md)
3535

3636
2. Install dependencies:
3737

@@ -195,7 +195,7 @@ For the PR titles you can refer to [this guide](CONTRIBUTING.md?plain=1#L60)
195195
196196
If you encounter any issues during development or testing, please check the following:
197197
198-
1. Ensure you're using the correct Node.js version (18.20.8 or higher) and npm version (10.8.2 or higher).
198+
1. Ensure you're using the correct Node.js version (24.11 or higher) and npm version (11.5.1 or higher).
199199
2. Clear the `node_modules` directory and reinstall dependencies if you encounter unexpected behavior.
200200
3. For Docker-related issues, make sure Docker is running and you have sufficient permissions.
201201

Dockerfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ARG NODE_VERSION=18
1+
ARG NODE_VERSION=24.11
22
FROM node:${NODE_VERSION}-alpine AS base
33

44
WORKDIR /app
@@ -28,6 +28,7 @@ FROM base AS final
2828

2929
# Copy package.json files extracted by turbo prune
3030
COPY --from=installer /out/json/ .
31+
COPY --from=installer /app/jest.config.base.js ./jest.config.base.js
3132
COPY --from=installer /out/package-lock.json ./package-lock.json
3233

3334
# Install dependencies only with package.json files to make use of cache
@@ -36,6 +37,9 @@ RUN npm ci --ignore-scripts
3637
# Copy the rest of the source code
3738
COPY --from=installer /out/full/ .
3839

40+
# turbo prune excludes runtime template assets
41+
COPY --from=installer /app/packages/templates ./packages/templates
42+
3943
# Change ownership of the /app directory to the node user
4044
RUN chown -R node:node /app
4145

apps/generator/CHANGELOG.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,83 @@
11
# @asyncapi/generator
22

3+
## 3.1.2
4+
5+
### Patch Changes
6+
7+
- 4a09f57: Bump @asyncapi/parser to 3.6.0 to support AsyncAPI 3.1.0
8+
9+
## 3.1.1
10+
11+
### Patch Changes
12+
13+
- 2bfad27: Fix generator handling of template parameters with `false` default values, ensuring defaults are correctly injected and conditional generation works as expected.
14+
15+
## 3.1.0
16+
17+
### Minor Changes
18+
19+
- 11a1b8d: - **Updated Component**: `OnMessage` (Python) - Added discriminator-based routing logic that automatically dispatches messages to operation-specific handlers before falling back to generic handlers
20+
21+
- **New Helpers**:
22+
- `getMessageDiscriminatorData` - Extracts discriminator key and value from individual messages
23+
- `getMessageDiscriminatorsFromOperations` - Collects all discriminator metadata from receive operations
24+
- Enhanced Python webSocket client generation with **automatic operation-based message routing**:
25+
26+
## How python routing works
27+
28+
- Generated WebSocket clients now automatically route incoming messages to operation-specific handlers based on message discriminators. Users can register handlers for specific message types without manually parsing or filtering messages.
29+
- When a message arrives, the client checks it against registered discriminators (e.g., `type: "hello"`, `type: "events_api"`)
30+
- If a match is found, the message is routed to the specific operation handler (e.g., `onHelloMessage`, `onEvent`)
31+
- If no match is found, the message falls back to generic message handlers
32+
- This enables clean separation of message handling logic based on message types
33+
34+
> `discriminator` is a `string` field that you can add to any AsyncAPI Schema. This also means that it is limited to AsyncAPI Schema only, and it won't work with other schema formats, like for example, Avro.
35+
36+
The implementation automatically derives discriminator information from your AsyncAPI document:
37+
38+
- Discriminator `key` is extracted from the `discriminator` field in your AsyncAPI spec
39+
- Discriminator `value` is extracted from the `const` property defined in message schemas
40+
41+
Example AsyncAPI Schema with `discriminator` and `const`:
42+
43+
```yaml
44+
schemas:
45+
hello:
46+
type: object
47+
discriminator: type # you specify name of property
48+
properties:
49+
type:
50+
type: string
51+
const: hello # you specify the value of the discriminator property that is used for routing
52+
description: A hello string confirming WebSocket connection
53+
```
54+
55+
## Fallback
56+
57+
When defaults aren't available in the AsyncAPI document, users must provide **both** `discriminator_key` and `discriminator_value` when registering handlers. Providing only one parameter is not supported - you must provide either both or neither.
58+
59+
> **Why this limitation exists**: When a receive operation has multiple messages sharing the same discriminator key (e.g., all use `"type"` field), we need the specific value (e.g., `"hello"`, `"disconnect"`) to distinguish between them. Without both pieces of information, the routing becomes ambiguous.
60+
61+
Example:
62+
63+
```python
64+
# Default case - discriminator info auto-derived from AsyncAPI doc
65+
client.register_on_hello_message_handler(my_handler)
66+
67+
# Custom case - must provide both key AND value
68+
client.register_on_hello_message_handler(
69+
my_handler,
70+
discriminator_key="message_type",
71+
discriminator_value="custom_hello"
72+
)
73+
```
74+
75+
### Patch Changes
76+
77+
- Updated dependencies [11a1b8d]
78+
- @asyncapi/generator-components@0.5.0
79+
- @asyncapi/generator-helpers@1.1.0
80+
381
## 3.0.1
482

583
### Patch Changes

apps/generator/docs/configuration-file.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ The `generator` property from `package.json` file must contain a JSON object and
159159
| `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.** |
160160
| `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**. |
161161
| `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). |
162-
| `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. |
162+
| `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. When you rely on a parameter here, make sure its default value declared in the `parameters` section uses the same data type your validation expects; mismatched types lead to failing conditions even when the defaults should allow generation. |
163163
| `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. |
164164
| `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. |
165165
| `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). |

apps/generator/docs/model-generation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ weight: 200
55

66
This guide will walk you through the process of enabling models/types generation in a template by using [Modelina](https://www.asyncapi.com/tools/modelina).
77

8-
Modelina is an AsyncAPI library designed for generating data models using inputs such as [AsyncAPI](generator/asyncapi-document), OpenAPI, or JSON schema inputs. Its functionality revolves around creating data models from the provided AsyncAPI document and the model template, which defines message payloads. It is better to use Modelina in your template to handle model generation rather than providing custom templates.
8+
Modelina is an AsyncAPI library designed for generating data models using inputs such as [AsyncAPI](asyncapi-document), OpenAPI, or JSON schema inputs. Its functionality revolves around creating data models from the provided AsyncAPI document and the model template, which defines message payloads. It is better to use Modelina in your template to handle model generation rather than providing custom templates.
99

1010
You can integrate the work shown in this guide into a template by following the [tutorial about creating a template](https://www.asyncapi.com/docs/tools/generator/generator-template).
1111

apps/generator/docs/template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Baked-in templates benefit from:
2929

3030
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.
3131

32-
Learn more from document [Baked-in Templates](#baked-in-templates).
32+
Learn more from document [Baked-in Templates](baked-in-templates).
3333

3434
### Standalone templates
3535

apps/generator/docs/usage.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,29 +40,29 @@ asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template
4040

4141
**The shortest possible syntax:**
4242
```bash
43-
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.0.0 --use-new-generator
43+
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4
4444
```
4545

4646
**Generating from a URL:**
4747
```bash
48-
asyncapi generate fromTemplate https://bit.ly/asyncapi @asyncapi/html-template@3.0.0 --use-new-generator
48+
asyncapi generate fromTemplate https://bit.ly/asyncapi @asyncapi/html-template@3.5.4
4949
```
5050

5151
**Specify where to put the result:**
5252
```bash
53-
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.0.0 --use-new-generator -o ./docs
53+
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4 -o ./docs
5454
```
5555

5656
**Passing parameters to templates:**
5757
```bash
58-
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.0.0 --use-new-generator -o ./docs -p title='Hello from param'
58+
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4 -o ./docs -p title='Hello from param'
5959
```
6060

61-
In the template you can use it like this: ` {{ params.title }}`
61+
In the template you can use it like this: `{{ params.title }}`
6262

6363
**Disabling the hooks:**
6464
```bash
65-
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.0.0 --use-new-generator -o ./docs -d generate:before generate:after=foo,bar
65+
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4 -o ./docs -d generate:before generate:after=foo,bar
6666
```
6767

6868
The generator skips all hooks of the `generate:before` type and `foo`, `bar` hooks of the `generate:after` type.
@@ -81,7 +81,7 @@ asyncapi generate fromTemplate asyncapi.yaml https://github.com/asyncapi/html-te
8181

8282
**Map schema references from baseUrl to local folder:**
8383
```bash
84-
asyncapi generate fromTemplate test/docs/apiwithref.json @asyncapi/html-template@3.0.0 --use-new-generator -o ./build/ --force-write --map-base-url https://schema.example.com/crm/:./test/docs/
84+
asyncapi generate fromTemplate test/docs/apiwithref.json @asyncapi/html-template@3.5.4 -o ./build/ --force-write --map-base-url https://schema.example.com/crm/:./test/docs/
8585
```
8686

8787
The parameter `--map-base-url` maps external schema references to local folders.
@@ -104,7 +104,7 @@ docker run --rm -it \
104104
--user=root \
105105
-v ${PWD}/test/fixtures/asyncapi_v1.yml:/app/asyncapi.yml \
106106
-v ${PWD}/output:/app/output \
107-
asyncapi/cli generate fromTemplate -o /app/output /app/asyncapi.yml @asyncapi/html-template@3.0.0 --use-new-generator --force-write
107+
asyncapi/cli generate fromTemplate -o /app/output /app/asyncapi.yml @asyncapi/html-template@3.5.4 --force-write
108108
```
109109
Note: Use ``` ` ``` instead of `\` for Windows.
110110

@@ -115,7 +115,7 @@ Note: Use ``` ` ``` instead of `\` for Windows.
115115
Use the following npx command on your terminal:
116116

117117
```bash
118-
npx -p @asyncapi/cli asyncapi generate fromTemplate ./asyncapi.yaml @asyncapi/html-template@3.0.0 --use-new-generator
118+
npx -p @asyncapi/cli asyncapi generate fromTemplate ./asyncapi.yaml @asyncapi/html-template@3.5.4
119119
```
120120

121121
## Using as a module/package

apps/generator/docs/versioning.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ It is better to lock a specific version of the template and the generator if you
1818
Generate HTML with the latest AsyncAPI CLI using the html-template.
1919
```
2020
npm install -g @asyncapi/cli
21-
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.0.0 --use-new-generator
21+
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4
2222
```
2323

24-
> AsyncAPI CLI has multiple versions of the generator, and to use the latest version, you may need to pass the `--use-new-generator` flag. For more details you can also check [asyncapi generate fromTemplate ASYNCAPI TEMPLATE](https://www.asyncapi.com/docs/tools/cli/usage#asyncapi-generate-fromtemplate-asyncapi-template)
2524

2625
Generate HTML using a particular version of the AsyncAPI CLI using the html-template.
2726

0 commit comments

Comments
 (0)