diff --git a/components/Asyncapi.js b/components/Asyncapi.js index deac63a62..d043c4aed 100644 --- a/components/Asyncapi.js +++ b/components/Asyncapi.js @@ -1,4 +1,3 @@ - import { Info } from './Info'; import { Servers } from './Servers'; import { Operations } from './Operations'; @@ -7,11 +6,13 @@ import { TableOfContents } from './TableOfContents'; // eslint-disable-next-line no-unused-vars import { AsyncAPIDocumentInterface } from '@asyncapi/parser'; +import { Operationsv3 } from './Operationsv3'; /** * @param {{asyncapi: AsyncAPIDocumentInterface, params: any}} param0 */ export function Asyncapi({ asyncapi, params }) { + const isV3 = asyncapi.version().split('.')[0] === '3'; return ( <> {params.frontMatter && } @@ -19,7 +20,11 @@ export function Asyncapi({ asyncapi, params }) { {params.toc !== 'false' && } - + { + isV3 ? + : + + } ); } diff --git a/components/Operations.js b/components/Operations.js index cae45ce43..8af591b08 100644 --- a/components/Operations.js +++ b/components/Operations.js @@ -10,7 +10,7 @@ import { SchemaHelpers } from '../helpers/schema'; import { FormatHelpers } from '../helpers/format'; // eslint-disable-next-line no-unused-vars -import { AsyncAPIDocumentInterface, OperationInterface, OperationReplyInterface, ChannelInterface } from '@asyncapi/parser'; +import { AsyncAPIDocumentInterface, OperationInterface, ChannelInterface } from '@asyncapi/parser'; /** * @param {{asyncapi: AsyncAPIDocumentInterface}} param0 @@ -78,15 +78,9 @@ function Operation({ asyncapi, type, operation, channelName, channel }) { // NOS const security = operation.security(); let renderedType; switch (type) { - case 'request': - renderedType = 'REQUEST'; - break; case 'publish': renderedType = 'PUB'; break; - case 'reply': - renderedType = 'REPLY'; - break; case 'subscribe': renderedType = 'SUB'; break; @@ -161,8 +155,6 @@ function Operation({ asyncapi, type, operation, channelName, channel }) { // NOS - - ); } @@ -204,74 +196,3 @@ function OperationMessages({ operation }) { ); } - -/** - * @param {{operation: OperationInterface}} param0 - */ -function OperationReply({ operation }) { - const reply = operation.reply(); - if (reply === undefined) { - return null; - } - const explicitChannel = reply.channel(); - - let type; - if (operation.isSend()) { - type = 'Request'; - } else if (operation.isReceive()) { - type = 'Response'; - } - - return ( - -
- {`${type} information`} -
- - {explicitChannel && {type} should be done to channel: `{explicitChannel.address()}`} - - - - <> - {reply.messages().length > 1 && ( - - Accepts **one of** the following messages: - - )} - {reply.messages().length > 1 && reply.messages().map((msg, idx) => ( - - ))} - - -
- ); -} - -/** - * @param {{reply: OperationReplyInterface}} param0 - */ -function OperationReplyAddress({ reply }) { - const address = reply.address(); - if (address === undefined) { - return null; - } - const location = address.location(); - - return ( - -
- {'Operation reply address information'} -
- - {address.hasDescription() && ( - - {address.description()} - - )} - - Operation reply address location: `{location}` - - -
- ); -} diff --git a/components/Operationsv3.js b/components/Operationsv3.js new file mode 100644 index 000000000..3a11f350b --- /dev/null +++ b/components/Operationsv3.js @@ -0,0 +1,295 @@ +import { Text } from '@asyncapi/generator-react-sdk'; +import { Bindings } from './Bindings'; +import { Extensions } from './Extensions'; +import { Message } from './Message'; +import { Schema } from './Schema'; +import { Security } from './Security'; +import { Tags } from './Tags'; +import { Header, ListItem, Link } from './common'; +import { SchemaHelpers } from '../helpers/schema'; +import { FormatHelpers } from '../helpers/format'; + +// eslint-disable-next-line no-unused-vars +import { AsyncAPIDocumentInterface, OperationInterface, OperationReplyInterface, ChannelInterface } from '@asyncapi/parser'; + +/** + * @param {{asyncapi: AsyncAPIDocumentInterface}} param0 + */ +export function Operationsv3({ asyncapi }) { + const channels = asyncapi.channels(); + if (channels.isEmpty()) { + return null; + } + + const operationsList = []; + for (const channel of channels.all()) { + const channelName = channel.address(); + const operations = channel.operations().all(); + operations.map(operation => { + let type; + if (operation.isSend()) { + if (operation.reply() !== undefined) { + type = 'request'; + } else { + type = 'send'; + } + } else if (operation.isReceive()) { + if (operation.reply() !== undefined) { + type = 'reply'; + } else { + type = 'receive'; + } + } + operationsList.push( + + ); + }); + } + + return ( + <> +
+ Operations +
+ {operationsList} + + ); +} + +/** + * @param {{asyncapi: AsyncAPIDocumentInterface, type: string, operation: OperationInterface, channelName: string, channel: ChannelInterface}} param0 + */ +function Operation({ asyncapi, type, operation, channelName, channel }) { // NOSONAR + if (!operation || !channel) { + return null; + } + + const operationId = operation.operationId(); + const externalDocs = operation.externalDocs(); + const applyToAllServers = asyncapi.servers().all().length === channel.servers().all().length; + const servers = applyToAllServers ? [] : channel.servers().all(); + const security = operation.security(); + let renderedType; + switch (type) { + case 'request': + renderedType = 'REQUEST'; + break; + case 'send': + renderedType = 'SEND'; + break; + case 'reply': + renderedType = 'REPLY'; + break; + case 'receive': + renderedType = 'RECEIVE'; + break; + } + const showInfoList = operationId || (servers?.length); + + return ( + +
+ {`${renderedType} \`${channelName}\` Operation`} +
+ + {operation.summary() && ( + + *{operation.summary().trim()}* + + )} + + {showInfoList ? ( + + {operationId && Operation ID: `{operationId}`} + {servers && servers.length && ( + + Available only on servers:{' '} + {servers.map(s => { + const serverId = s.id(); + const slug = FormatHelpers.slugify(serverId); + return `[${serverId}](#${slug}-server)`; + }).join(', ')} + + )} + + ) : null} + + {channel.hasDescription() && ( + + {channel.description()} + + )} + {operation.hasDescription() && ( + + {operation.description()} + + )} + + {externalDocs && ( + + + {externalDocs.description() || 'Find more info here.'} + + + )} + + + + + + + + + + + + + + + + +
+ ); +} +/** + * @param {{channel: ChannelInterface}} param0 + */ +function OperationParameters({ channel }) { + const parameters = SchemaHelpers.parametersToSchema(channel.parameters().all()); + if (!parameters) { + return null; + } + + return ( + +
Parameters
+ +
+ ); +} +/** + * @param {{operation: OperationInterface}} param0 + */ +function OperationMessages({ operation, type }) { + const messages = operation.messages().all(); + if (messages.length === 0) { + return null; + } + + let messagesText = 'Accepts **one of** the following messages:'; + if (type === 'send') { + messagesText = 'Sending **one of** the following messages:'; + } else if (type === 'request') { + messagesText = 'Request contains **one of** the following messages:'; + } else if (type === 'receive') { + messagesText = 'Receive **one of** the following messages:'; + } else if (type === 'reply') { + messagesText = 'Request contains **one of** the following messages:'; + } + + return ( + <> + {messages.length > 1 && ( + + {messagesText} + + )} + {messages.map((msg, idx) => ( + + ))} + + ); +} + +/** + * @param {{operation: OperationInterface}} param0 + */ +function OperationReply({ operation, type }) { + const reply = operation.reply(); + if (reply === undefined) { + return null; + } + const explicitChannel = reply.channel(); + + let typeText; + if (operation.isSend()) { + typeText = 'Request'; + } else if (operation.isReceive()) { + typeText = 'Response'; + } + + let messagesText = 'Accepts **one of** the following messages:'; + if (type === 'request') { + messagesText = 'Receive **one of** the following messages as a response to the request:'; + } else if (type === 'reply') { + messagesText = 'Replying with **one of** the following messages:'; + } + + return ( + +
+ {`${typeText} information`} +
+ + {explicitChannel && {type} should be done to channel: `{explicitChannel.address()}`} + + + + <> + {reply.messages().length > 1 && ( + + {messagesText} + + )} + {reply.messages().length > 1 && reply.messages().map((msg, idx) => ( + + ))} + + +
+ ); +} + +/** + * @param {{reply: OperationReplyInterface}} param0 + */ +function OperationReplyAddress({ reply }) { + const address = reply.address(); + if (address === undefined) { + return null; + } + const location = address.location(); + + return ( + +
+ {'Operation reply address information'} +
+ + {address.hasDescription() && ( + + {address.description()} + + )} + + Operation reply address location: `{location}` + + +
+ ); +} diff --git a/package.json b/package.json index 66a88c06b..50f1cfd65 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "test:generator": "npm run test:generator:v2 && npm run test:generator:v3", "test:generator:v2": "asyncapi generate fromTemplate ./test/spec/asyncapi_v2.yml ./ -o test/output --force-write", "test:generator:v3": "asyncapi generate fromTemplate ./test/spec/asyncapi_v3.yml ./ -o test/output --force-write", + "dev": "asyncapi generate fromTemplate ./test/spec/asyncapi_v2.yml ./ -o test/output --force-write --watch-template", "lint": "eslint --max-warnings 0 --config \".eslintrc\" \".\"", "lint:fix": "eslint --max-warnings 0 --config \".eslintrc\" \".\" --fix", "generate:assets": "npm run generate:readme:toc",