Skip to content

Commit

Permalink
feat: toc and operation reply (#523)
Browse files Browse the repository at this point in the history
  • Loading branch information
korifey91 authored Apr 18, 2024
1 parent b0af92a commit b709ff7
Show file tree
Hide file tree
Showing 11 changed files with 49,680 additions and 14,860 deletions.
84 changes: 26 additions & 58 deletions components/Operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@ import { Tags } from './Tags';
import { Header, ListItem, Link } from './common';
import { SchemaHelpers } from '../helpers/schema';
import { FormatHelpers } from '../helpers/format';
import { CommonHelpers } from '../helpers/common';

// eslint-disable-next-line no-unused-vars
import { AsyncAPIDocumentInterface, OperationInterface, ChannelInterface } from '@asyncapi/parser';

function isV3({asyncapi}) {
return asyncapi.version().split('.')[0] === '3';
}

/**
* @param {{asyncapi: AsyncAPIDocumentInterface}} param0
* @param {{asyncapi: AsyncAPIDocumentInterface}} param0
*/
export function Operations({ asyncapi }) {
const channels = asyncapi.channels();
Expand All @@ -30,20 +27,8 @@ export function Operations({ asyncapi }) {
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';
}
}
const type = CommonHelpers.getOperationType(operation, asyncapi);

operationsList.push(
<Operation
key={`${operation.action()}-${channelName}`}
Expand All @@ -66,52 +51,28 @@ export function Operations({ asyncapi }) {
</>
);
}
function getRenderedTypeForOperation({asyncapi, type}) {
const isv3 = isV3({asyncapi});
if (isv3) {
switch (type) {
case 'request':
return 'REQUEST';
case 'send':
return 'SEND';
case 'reply':
return 'REPLY';
case 'receive':
return 'RECEIVE';
}
}
// For v2, we render the application view still
// Meaning the when you use publish operation it means other publish to your application because your application is subscribing to it.
switch (type) {
case 'send': // This is the publish operation
return 'SUB';
case 'receive': // This is the subscribe operation
return 'PUB';
}
// This case should never happen, if it does this function needs to be changed
return 'UNKNOWN';
}
/**
* @param {{asyncapi: AsyncAPIDocumentInterface, type: string, operation: OperationInterface, channelName: string, channel: ChannelInterface}} param0
* @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 isV3Doc = CommonHelpers.isV3(asyncapi);
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();
const renderedType = getRenderedTypeForOperation({asyncapi, type});

const showInfoList = operationId || (servers && servers.length);
const typeToRender = isV3Doc ? type.toUpperCase() : type.slice(0, 3).toUpperCase();

return (
<Text>
<Header type={3}>
{`${renderedType} \`${channelName}\` Operation`}
{`${typeToRender} \`${channelName}\` Operation`}
</Header>

{operation.summary() && (
Expand Down Expand Up @@ -177,13 +138,13 @@ function Operation({ asyncapi, type, operation, channelName, channel }) { // NOS

<OperationMessages operation={operation} asyncapi={asyncapi} type={type} />

<OperationReply operation={operation} />
<OperationReply operation={operation} type={type} />
</Text>
);
}

/**
* @param {{channel: ChannelInterface}} param0
* @param {{channel: ChannelInterface}} param0
*/
function OperationParameters({ channel }) {
const parameters = SchemaHelpers.parametersToSchema(channel.parameters().all());
Expand All @@ -200,7 +161,7 @@ function OperationParameters({ channel }) {
}
function getOperationMessageText({asyncapi, type}) {
let messagesText = 'Accepts **one of** the following messages:';
if (isV3({asyncapi})) {
if (CommonHelpers.isV3(asyncapi)) {
if (type === 'send') {
messagesText = 'Sending **one of** the following messages:';
} else if (type === 'request') {
Expand All @@ -214,7 +175,7 @@ function getOperationMessageText({asyncapi, type}) {
return messagesText;
}
/**
* @param {{operation: OperationInterface, asyncapi: AsyncAPIDocumentInterface, type: string}} param0
* @param {{operation: OperationInterface, asyncapi: AsyncAPIDocumentInterface, type: string}} param0
*/
function OperationMessages({ asyncapi, operation, type }) {
const messages = operation.messages().all();
Expand All @@ -238,13 +199,18 @@ function OperationMessages({ asyncapi, operation, type }) {
}

/**
* @param {{operation: OperationInterface}} param0
* @param {{operation: OperationInterface}} param0
*/
function OperationReply({ operation, type }) {
const reply = operation.reply();
if (reply === undefined) {
return null;
}

const replyMessages = reply.messages().length
? reply.messages()
: reply.channel().messages();

const explicitChannel = reply.channel();

let typeText;
Expand All @@ -267,17 +233,19 @@ function OperationReply({ operation, type }) {
{`${typeText} information`}
</Header>

{explicitChannel && <ListItem>{type} should be done to channel: `{explicitChannel.address()}`</ListItem>}

<OperationReplyAddress name="Operation reply address" reply={reply} />
{explicitChannel?.address() ? (
<ListItem>{type} should be done to channel: `{explicitChannel.address()}`</ListItem>
) : (
<OperationReplyAddress name="Operation reply address" reply={reply} />
)}

<>
{reply.messages().length > 1 && (
{replyMessages.length > 1 && (
<Text newLines={2}>
{messagesText}
</Text>
)}
{reply.messages().length > 1 && reply.messages().map((msg, idx) => (
{replyMessages.all().map((msg, idx) => (
<Message message={msg} key={`message-${idx}`} />
))}
</>
Expand All @@ -287,7 +255,7 @@ function OperationReply({ operation, type }) {
}

/**
* @param {{reply: OperationReplyInterface}} param0
* @param {{reply: OperationReplyInterface}} param0
*/
function OperationReplyAddress({ reply }) {
const address = reply.address();
Expand Down
89 changes: 48 additions & 41 deletions components/TableOfContents.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,71 @@
import { Text, Indent, IndentationTypes } from '@asyncapi/generator-react-sdk';

import { Header, Link, ListItem } from '../components/common';

import { FormatHelpers } from '../helpers/format';
import { CommonHelpers } from '../helpers/common';

export function TableOfContents({ asyncapi }) {
const serversList = asyncapi.servers().all().map(server => {
const serverName = server.id();
return (
<Indent size={2} type={IndentationTypes.SPACES} key={serverName}>
<ListItem>
<Link href={`#${FormatHelpers.slugify(serverName)}-server`}>{serverName}</Link>
</ListItem>
</Indent>
);
});
import { Header, Link, ListItem } from './common';

const operationsList = [];
asyncapi.channels().all().map(channel => {
const channelName = channel.address();
channel.operations().all().forEach(operation => {
if (operation.action() === 'publish') {
operationsList.push(
<Indent size={2} type={IndentationTypes.SPACES} key={`pub-${channelName}`}>
<ListItem>
<Link href={`#pub-${FormatHelpers.slugify(channelName)}-operation`}>PUB {channelName}</Link>
</ListItem>
</Indent>
);
}
if (operation.action() === 'subscribe') {
operationsList.push(
<Indent size={2} type={IndentationTypes.SPACES} key={`sub-${channelName}`}>
<ListItem>
<Link href={`#sub-${FormatHelpers.slugify(channelName)}-operation`}>SUB {channelName}</Link>
</ListItem>
</Indent>
);
}
});
});
export function TableOfContents({asyncapi}) {
const servers = asyncapi.servers().all();
const operations = asyncapi.operations().all();
const isV3Doc = CommonHelpers.isV3(asyncapi);

return (
<>
<Header type={2}>Table of Contents</Header>
<Text>
{serversList.length > 0 && (
{servers.length > 0 && (
<>
<ListItem>
<Link href="#servers">Servers</Link>
</ListItem>
{serversList}
{servers.map((server) => {
const serverName = server.id();
return (
<Indent
size={2}
type={IndentationTypes.SPACES}
key={serverName}
>
<ListItem>
<Link href={`#${FormatHelpers.slugify(
serverName)}-server`}>
{serverName}
</Link>
</ListItem>
</Indent>
);
})}
</>
)}
{operationsList.length > 0 && (
{operations.length > 0 && (
<>
<ListItem>
<Link href="#operations">Operations</Link>
</ListItem>
{operationsList}
{operations.map((operation) => {
const channel = operation.channels().all()[0];
const channelAddress = channel?.address() ?? '';
const type = CommonHelpers.getOperationType(operation, asyncapi);
const typeToRender = isV3Doc ? type : type.slice(0, 3);

return (
<Indent
size={2}
type={IndentationTypes.SPACES}
key={`${typeToRender}-${channelAddress}`}
>
<ListItem>
<Link
href={`#${typeToRender}-${FormatHelpers.slugify(
channelAddress)}-operation`}
>
{typeToRender.toUpperCase()} {channelAddress}
</Link>
</ListItem>
</Indent>
);
})}
</>
)}
</Text>
Expand Down
43 changes: 43 additions & 0 deletions helpers/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const OPERATION_TYPES = {
V3: {
REQUEST: 'request',
SEND: 'send',
REPLY: 'reply',
RECEIVE: 'receive',
},
// For v2, when you use publish operation it means
// other publish to your application because your application is subscribing to it.
V2: {
REQUEST: 'publish',
SEND: 'subscribe',
REPLY: 'subscribe',
RECEIVE: 'publish',
}
};

const getOperationTypesByVersion = (version) => {
const [majorVersion] = version.split('.');

return OPERATION_TYPES[`V${majorVersion}`];
};

export class CommonHelpers {
static getOperationType(operation, asyncApiDoc) {
const operationsTypes = getOperationTypesByVersion(asyncApiDoc.version());

if (operation.isSend()) {
if (operation.reply() !== undefined) {
return operationsTypes.REQUEST;
}
return operationsTypes.SEND;
}
if (operation.isReceive() && operation.reply() !== undefined) {
return operationsTypes.REPLY;
}
return operationsTypes.RECEIVE;
}

static isV3(asyncApiDoc) {
return asyncApiDoc.version().split('.')[0] === '3';
}
}
Loading

0 comments on commit b709ff7

Please sign in to comment.