add DTO object generator

This commit is contained in:
marys
2026-06-03 15:08:11 +02:00
parent 4daa2241c7
commit dd31750e1a
17 changed files with 190 additions and 3306 deletions
+2 -1
View File
@@ -1,4 +1,5 @@
https://www.asyncapi.com/docs/tools/generator/generator-template#overview-of-steps https://www.asyncapi.com/docs/tools/generator/generator-template#overview-of-steps
asyncapi generate fromTemplate openapi_templete/test/fixtures/asyncapi_test.yaml ./openapi_templete -o ./generated-code --force-write asyncapi generate fromTemplate openapi_templete/test/fixtures/asyncapi_test.yaml ./openapi_templete -o ./generated-code --force-write
asyncapi generate fromTemplate openapi_templete/test/fixtures/asyncapi_1.yaml ./openapi_templete -o ./generated-code --force-write
+2 -2
View File
@@ -62,8 +62,8 @@ components:
name: mtr_request name: mtr_request
payload: payload:
type: object type: object
# required: required:
# - to_server - to_server
$ref: '#/components/schemas/mtr_request_schema' $ref: '#/components/schemas/mtr_request_schema'
mtr_uuid: mtr_uuid:
payload: payload:
-24
View File
@@ -1,24 +0,0 @@
{
"name": "@your-org/asyncapi-python-template",
"version": "1.0.0",
"description": "Custom Python async client generator for AsyncAPI",
"generator": {
"supportedProtocols": ["mqtt", "kafka", "nats"],
"parameters": {
"client_name": {
"description": "Name of the generated client class",
"default": "AsyncClient",
"required": false
},
"async_mode": {
"description": "Enable async/await support",
"default": true,
"required": false
}
}
},
"dependencies": {
"@asyncapi/generator-react-sdk": "^1.1.0",
"@asyncapi/modelina": "^4.0.0"
}
}
-8
View File
@@ -1,8 +0,0 @@
module.exports = {
'generate:before': ({ asyncapi, templateParams = {} }) => {
// Modify the AsyncAPI document before generation
if (templateParams.version) {
asyncapi._json.info.version = templateParams.version;
}
}
};
-56
View File
@@ -1,56 +0,0 @@
import { File, Text } from "@asyncapi/generator-react-sdk";
import { PythonGenerator, FormatHelpers } from "@asyncapi/modelina";
export default async function({ asyncapi, params, originalAsyncAPI }) {
const files = [];
// Generate Python data models using Modelina
const pythonGenerator = new PythonGenerator();
const models = await pythonGenerator.generate(asyncapi);
// Create models.py file
const modelsContent = models.map(model =>
`# ${model.modelName}\n${model.result}\n`
).join('\n');
files.push(
<File name="models.py">
<Text>"""Auto-generated Python models from AsyncAPI spec."""</Text>
<Text>{modelsContent}</Text>
</File>
);
// Generate async client
files.push(
<File name="client.py">
<Text>{generateClientCode(asyncapi, params)}</Text>
</File>
);
return files;
}
function generateClientCode(asyncapi, params) {
const clientName = params.client_name || "AsyncClient";
const servers = asyncapi.servers().all();
let code = `"""Auto-generated async client for ${asyncapi.info().title()}"""\n\n`;
code += `import asyncio\nimport aiohttp\n\n`;
code += `class ${clientName}:\n`;
code += ` """Async client for ${asyncapi.info().title()}"""\n\n`;
code += ` def __init__(self, host: str):\n`;
code += ` self.host = host\n`;
code += ` self.session = None\n\n`;
// Add methods for each channel/operation
asyncapi.channels().all().forEach(channel => {
const channelName = FormatHelpers.toCamelCase(channel.address() || channel.name());
code += ` async def ${channelName}_publish(self, payload):\n`;
code += ` """Publish to ${channel.name()}"""\n`;
code += ` if not self.session:\n`;
code += ` self.session = aiohttp.ClientSession()\n`;
code += ` # Implementation for ${channel.name()}\n\n`;
});
return code;
}
-8
View File
@@ -1,8 +0,0 @@
{
"name": "python-async-template",
"generator": {},
"dependencies": {
"@asyncapi/generator-react-sdk": "^1.1.0",
"@asyncapi/modelina": "^4.0.0"
}
}
-3130
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -8,9 +8,10 @@
"supportedProtocols": ["mqtt"] "supportedProtocols": ["mqtt"]
}, },
"dependencies": { "dependencies": {
"@asyncapi/generator-react-sdk": "^0.2.25" "@asyncapi/generator-react-sdk": "^1.1.2",
"@asyncapi/modelina": "^5.10.1"
}, },
"devDependencies": { "devDependencies": {
"rimraf": "^5.0.0" "rimraf": "^5.0.0"
} }
} }
-2
View File
@@ -6,8 +6,6 @@
// return <File name="client.py">{asyncapi.info().title()}</File> // return <File name="client.py">{asyncapi.info().title()}</File>
// } // }
import { File } from '@asyncapi/generator-react-sdk'; import { File } from '@asyncapi/generator-react-sdk';
export default function ({ asyncapi }) { export default function ({ asyncapi }) {
+15 -3
View File
@@ -9,21 +9,33 @@
import { File } from '@asyncapi/generator-react-sdk'; import { File } from '@asyncapi/generator-react-sdk';
import { PythonGenerator, FormatHelpers } from '@asyncapi/modelina';
export default function ({ asyncapi, params }) { export default async function ({ asyncapi, params }) {
const channels = Object.keys(asyncapi.components()); const channels = Object.keys(asyncapi.components());
let content = '' let content = ''
for (const channel of channels) { for (const channel of channels) {
content += `# channel: ${channel}\n` content += `# channel: ${channel}\n`
} }
const pythonGenerator = new PythonGenerator();
const models = await pythonGenerator.generate(asyncapi);
const files = [];
for (const model of models) {
const modelFileName = `${FormatHelpers.toPascalCase(model.modelName)}.py`;
files.push(modelFileName);
}
return ( return (
<File name="client2.py"># {asyncapi.info().title()} <File name="client2.py"># {asyncapi.info().title()}
{`\n`} {`\n`}
# {asyncapi.info().description()} # {asyncapi.info().description()}
{`\n`} {`\n`}
{channels.map((ch) => `# channel: ${ch}\n`)} # {channels.map((ch) => `# channel: ${ch}\n`)}
{content} # {content}
# {'=========='}
# {files}
# {'=========='}
</File> </File>
) )
} }
@@ -0,0 +1,13 @@
import { File } from '@asyncapi/generator-react-sdk';
import { PythonGenerator, FormatHelpers } from '@asyncapi/modelina';
export default async function schemaRender({ asyncapi }) {
const pythonGenerator = new PythonGenerator();
const models = await pythonGenerator.generate(asyncapi);
const files = [];
for (const model of models) {
files.push(model.model)
}
return <File name="debug.py">{JSON.stringify(models, null, 2)}</File>
}
@@ -0,0 +1,33 @@
// 1
import { File } from '@asyncapi/generator-react-sdk';
// 2
import { PythonGenerator, FormatHelpers } from '@asyncapi/modelina';
/**
* @typedef RenderArgument
* @type {object}
* @property {AsyncAPIDocument} asyncapi document object received from the generator.
*/
/**
* Render all schema models
* @param {RenderArgument} param0
* @returns
*/
// 3
export default async function schemaRender({ asyncapi }) {
// 4
const pythonGenerator = new PythonGenerator();
// 5
const models = await pythonGenerator.generate(asyncapi);
// 6
const files = [];
// 7
for (const model of models) {
// 8
const modelFileName = `${FormatHelpers.toPascalCase(model.modelName)}.py`;
// 9
files.push(<File name={modelFileName}>{model.result}</File>);
}
return files;
}
+122
View File
@@ -0,0 +1,122 @@
asyncapi: 3.0.0
info:
title: Order Service (NATS)
version: 1.0.0
description: Event-driven order service using NATS
servers:
nats:
host: nats://localhost:4222
protocol: nats
description: Local NATS server
channels:
order.created:
address: order.created
messages:
OrderCreated:
$ref: '#/components/messages/OrderCreated'
order.placed:
address: order.placed
messages:
OrderPlaced:
$ref: '#/components/messages/OrderPlaced'
operations:
onOrderCreated:
action: receive
channel:
$ref: '#/channels/order.created'
messages:
- $ref: '#/channels/order.created/messages/OrderCreated'
onOrderPlaced:
action: send
channel:
$ref: '#/channels/order.placed'
messages:
- $ref: '#/channels/order.placed/messages/OrderPlaced'
components:
messages:
OrderCreated:
name: OrderCreated
title: Order Created
summary: Event emitted when an order is created.
payload:
$ref: '#/components/schemas/OrderCreated'
OrderPlaced:
name: OrderPlaced
title: Order Placed
summary: Event emitted when an order is placed.
payload:
$ref: '#/components/schemas/OrderPlaced'
schemas:
OrderCreated:
$id: OrderCreated
title: OrderCreated
type: object
required:
- orderId
- customerId
- createdAt
properties:
orderId:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440000"
customerId:
type: string
example: "cust-123"
createdAt:
type: string
format: date-time
example: "2025-06-03T12:00:00Z"
status:
type: string
enum:
- created
- pending
- confirmed
default: created
OrderPlaced:
$id: OrderPlaced
title: OrderPlaced
type: object
required:
- orderId
- customerId
- items
- placedAt
properties:
orderId:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440001"
customerId:
type: string
example: "cust-123"
items:
type: array
items:
type: object
required:
- productId
- quantity
properties:
productId:
type: string
quantity:
type: integer
minimum: 1
placedAt:
type: string
format: date-time
example: "2025-06-03T12:05:00Z"
totalAmount:
type: number
format: double
-70
View File
@@ -1,70 +0,0 @@
# .venv/bin/asyncapi-python-codegen asyncapi.yaml out --force-write
# kouknout na FastStream
# https://nats.io/blog/nats-supported-by-faststream/#writing-app-code
# https://github.com/asyncapi/python-paho-template
# https://www.asyncapi.com/docs/tools/generator/generator-template
# https://www.asyncapi.com/docs/tools/generator/generator-template --force-write
# https://pypi.org/project/asyncapi-python/
# https://github.com/G-USI/asyncapi-python
asyncapi: 3.0.0
info:
title: Job Events
version: 1.0.0
servers:
nats_localhost:
host: localhost:4222
protocol: nats
channels:
run_test:
address: mtr_test.run_test
messages:
run_test:
$ref: '#/components/messages/mtr_request'
return_uuid:
address: null
messages:
run_test:
$ref: '#/components/messages/mtr_uuid'
operations:
get_mtr_test:
action: send
channel:
$ref: '#/channels/run_test'
reply:
address:
location: "$message.header#/replayTo"
channel:
$ref: '#/channels/return_uuid'
components:
schemas:
mtr_request_schema:
payload:
type: object
properties:
to_server:
type: string
mtr_sleep:
type: integer
mtr_uuid_schema:
payload:
type: object
properties:
uuid:
type: string
messages:
mtr_request:
name: mtr_request
payload:
type: object
# required:
# - to_server
$ref: '#/components/schemas/mtr_request_schema'
mtr_uuid:
payload:
$ref: '#/components/schemas/mtr_uuid_schema'