|
1 | 1 | import json
|
2 |
| -import logging |
| 2 | +from typing import Dict, Literal, List |
3 | 3 |
|
4 | 4 | import pydantic_asyncapi as pa
|
5 | 5 | from fastapi import APIRouter
|
6 |
| -from pydantic.json_schema import models_json_schema |
7 | 6 | from starlette.responses import HTMLResponse
|
8 | 7 |
|
9 | 8 | from domains.books.events import BookCreatedV1, BookUpdatedV1
|
10 | 9 |
|
11 |
| -message_map = { |
12 |
| - # Use validation if receiving message, serialization if sending message |
13 |
| - "chat_channel": [(BookCreatedV1, "validation"), (BookUpdatedV1, "validation")] |
| 10 | +asyncapi_registry: Dict[str, Dict[Literal["receive", "send"], List]] = { |
| 11 | + "chat_channel": { |
| 12 | + "receive": [BookCreatedV1], |
| 13 | + "send": [BookUpdatedV1], |
| 14 | + } |
14 | 15 | }
|
15 | 16 |
|
16 | 17 | components_schemas = {}
|
17 |
| -channel_messages = {} |
18 |
| - |
19 |
| -# Prepare some data from a map |
20 |
| -for channel, messages in message_map.items(): |
21 |
| - channel_messages[channel] = {} |
22 |
| - a, b = models_json_schema(models=messages, ref_template="#/components/schemas/{model}") |
23 | 18 |
|
24 |
| - logging.error(a) |
25 |
| - """ |
26 |
| - {(<class 'domains.books.events.BookCreatedV1'>, 'validation'): {'$ref': '#/components/schemas/BookCreatedV1'}, (<class 'domains.books.events.BookUpdatedV1'>, 'validation'): {'$ref': '#/components/schemas/BookUpdatedV1'}} |
27 |
| - """ |
28 |
| - logging.error(b) |
29 |
| - |
30 |
| - components_schemas = b["$defs"] |
31 |
| - # TODO: Check for overlapping model schemas, if they are different log a warning! |
32 |
| - for message in messages: |
33 |
| - # components_schemas[message.__name__] = message.model_json_schema(ref_template="#/components/schemas/{model}") |
34 |
| - # components_schemas.update(message.model_json_schema(ref_template="#/components/schemas/{model}")["$defs"]) |
35 |
| - # channel_messages[channel][message.__name__] = pa.v3.Message( |
36 |
| - # payload=pa.v3.Reference(ref=f"#/components/schemas/{message.__name__}") |
37 |
| - # ) |
38 |
| - channel_messages[channel][message[0].__name__] = pa.v3.Message( |
39 |
| - payload=pa.v3.Reference(ref=f"#/components/schemas/{message[0].__name__}") |
| 19 | +channels = {} |
| 20 | +operations = {} |
| 21 | + |
| 22 | +for channel, channel_operations in asyncapi_registry.items(): |
| 23 | + _channel_messages = {} |
| 24 | + for operation, messages in channel_operations.items(): |
| 25 | + _operation_message_refs = [] |
| 26 | + for message in messages: |
| 27 | + # TODO: Check for overlapping model schemas, if they are different log a warning! |
| 28 | + components_schemas[message.__name__] = message.model_json_schema( |
| 29 | + mode="validation" if operation == "receive" else "serialization", |
| 30 | + ref_template="#/components/schemas/{model}" |
| 31 | + ) |
| 32 | + components_schemas.update(message.model_json_schema(mode="serialization", ref_template="#/components/schemas/{model}")["$defs"]) |
| 33 | + _channel_messages[message.__name__] = pa.v3.Message( |
| 34 | + payload=pa.v3.Reference(ref=f"#/components/schemas/{message.__name__}") |
| 35 | + ) |
| 36 | + # Cannot point to the /components path |
| 37 | + _operation_message_refs.append(pa.v3.Reference(ref=f"#/channels/chat_channel/messages/{message.__name__}")) |
| 38 | + operations[operation] = pa.v3.Operation( |
| 39 | + action=operation, |
| 40 | + channel=pa.v3.Reference(ref=f"#/channels/{channel}"), |
| 41 | + messages=_operation_message_refs, |
40 | 42 | )
|
| 43 | + channels[channel] = pa.v3.Channel( |
| 44 | + title=channel, |
| 45 | + servers=[pa.v3.Reference(ref="#/servers/chat")], |
| 46 | + messages=_channel_messages, |
| 47 | + ) |
| 48 | + |
41 | 49 |
|
42 | 50 |
|
43 | 51 | schema = pa.AsyncAPIV3(
|
|
56 | 64 | protocol="websocket",
|
57 | 65 | )
|
58 | 66 | },
|
59 |
| - channels={ |
60 |
| - "chat_channel": pa.v3.Channel( |
61 |
| - title="chat_channel_title", |
62 |
| - servers=[pa.v3.Reference(ref="#/servers/chat")], |
63 |
| - messages=channel_messages["chat_channel"], |
64 |
| - ) |
65 |
| - }, |
66 |
| - operations={ |
67 |
| - "chat_operation": pa.v3.Operation( |
68 |
| - action="receive", |
69 |
| - channel=pa.v3.Reference(ref="#/channels/chat_channel"), |
70 |
| - ) |
71 |
| - }, |
72 |
| - |
| 67 | + channels=channels, |
| 68 | + operations=operations, |
73 | 69 | )
|
74 | 70 |
|
75 | 71 | router = APIRouter(prefix="/docs/ws")
|
|
0 commit comments