Skip to content

Commit 93b26e7

Browse files
authored
feat: add support for message.examples (#176)
1 parent f0e5f8a commit 93b26e7

File tree

14 files changed

+214
-1960
lines changed

14 files changed

+214
-1960
lines changed

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ jobs:
4646
# Web-component
4747
- name: Install latest version of library in the web-component # this will update package.json and a lock file for the web-component that will also be pushed to PR with next step
4848
if: steps.initversion.outputs.version != steps.extractver.outputs.version
49-
# sleep for 10 seconds before using latest version in web-component, because sometimes NPM needs additional few seconds to `saves` package in registry
49+
# sleep for 20 seconds before using latest version in web-component, because sometimes NPM needs additional few seconds to `saves` package in registry
5050
run: |
51-
sleep 10
51+
sleep 20
5252
npm install @kyma-project/asyncapi-react@${{ steps.extractver.outputs.version }} -s
5353
working-directory: ./web-component
5454
- name: Build web-component

library/src/containers/Messages/Message.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import React from 'react';
33
import { SchemaComponent } from '../Schemas/Schema';
44
import { PayloadComponent } from './Payload';
55

6-
import { bemClasses, removeSpecialChars } from '../../helpers';
6+
import {
7+
bemClasses,
8+
removeSpecialChars,
9+
getExamplesFromSpec,
10+
} from '../../helpers';
711
import { Message, isRawMessage } from '../../types';
812

913
import { Markdown, Badge, BadgeType, Toggle } from '../../components';
@@ -72,6 +76,7 @@ export const MessageComponent: React.FunctionComponent<Props> = ({
7276
}
7377

7478
title = title || message.title || message.name;
79+
const examples = message.examples;
7580

7681
const summary = message.summary && (
7782
<div className={bemClasses.element(`${className}-summary`)}>
@@ -108,6 +113,7 @@ export const MessageComponent: React.FunctionComponent<Props> = ({
108113
const headersID = !inChannel
109114
? bemClasses.identifier([{ id: messageID, toKebabCase: false }, 'headers'])
110115
: undefined;
116+
111117
const headers = message.headers && (
112118
<section
113119
className={bemClasses.element(`${className}-headers`)}
@@ -123,6 +129,7 @@ export const MessageComponent: React.FunctionComponent<Props> = ({
123129
schema={message.headers}
124130
exampleTitle={HEADERS_EXAMPLE_TEXT}
125131
hideTitle={true}
132+
examples={examples && getExamplesFromSpec(examples, 'headers')}
126133
/>
127134
</div>
128135
</section>
@@ -142,6 +149,7 @@ export const MessageComponent: React.FunctionComponent<Props> = ({
142149
payload={message.payload}
143150
identifier={payloadID}
144151
dataIdentifier={payloadDataID}
152+
examples={examples && getExamplesFromSpec(examples, 'payload')}
145153
/>
146154
);
147155

library/src/containers/Messages/Payload.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface Props extends Required<Pick<RawMessage, 'payload'>> {
1919
identifier?: string;
2020
dataIdentifier?: string;
2121
id?: number;
22+
examples?: object[];
2223
}
2324

2425
export const PayloadComponent: React.FunctionComponent<Props> = ({
@@ -28,6 +29,7 @@ export const PayloadComponent: React.FunctionComponent<Props> = ({
2829
identifier,
2930
dataIdentifier,
3031
id,
32+
examples,
3133
}) => {
3234
const className = `message-payload`;
3335
const payloadsID = identifier ? `${identifier}s` : undefined;
@@ -54,6 +56,7 @@ export const PayloadComponent: React.FunctionComponent<Props> = ({
5456
oneOf={true}
5557
identifier={identifier}
5658
id={index}
59+
examples={examples}
5760
/>
5861
</li>
5962
))}
@@ -84,6 +87,7 @@ export const PayloadComponent: React.FunctionComponent<Props> = ({
8487
anyOf={true}
8588
identifier={identifier}
8689
id={index}
90+
examples={examples}
8791
/>
8892
</li>
8993
))}
@@ -105,6 +109,7 @@ export const PayloadComponent: React.FunctionComponent<Props> = ({
105109
schema={payload}
106110
exampleTitle={PAYLOAD_EXAMPLE_TEXT}
107111
hideTitle={true}
112+
examples={examples}
108113
/>
109114
</div>
110115
);

library/src/containers/Schemas/Schema.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ interface Props {
2020
hideTitle?: boolean;
2121
toggle?: boolean;
2222
toggleExpand?: boolean;
23+
examples?: object[];
2324
}
2425

2526
const renderSchemaProps = (
@@ -52,6 +53,7 @@ export const SchemaComponent: React.FunctionComponent<Props> = ({
5253
hideTitle = false,
5354
toggle = false,
5455
toggleExpand = false,
56+
examples = [],
5557
}) => {
5658
if (!schema) {
5759
return null;
@@ -68,14 +70,22 @@ export const SchemaComponent: React.FunctionComponent<Props> = ({
6870
</span>
6971
</h3>
7072
);
71-
73+
const hasExamples = examples.length;
7274
const content = (
7375
<>
7476
<div className={`${bemClasses.element(`${className}-table`)} p-4`}>
7577
{renderSchemaProps(name, schema)}
7678
</div>
77-
{/* we need to disable this component if schema has "not" field anywhere in it */}
78-
{hasNotField ? null : (
79+
80+
{hasExamples ? (
81+
examples.map((el, i) => (
82+
<SchemaExampleComponent
83+
title={hasExamples > 1 ? `${exampleTitle} ${i}` : exampleTitle}
84+
example={el}
85+
key={i}
86+
/>
87+
)) // we need to disable this component if schema has "not" field anywhere in it
88+
) : hasNotField ? null : (
7989
<SchemaExampleComponent title={exampleTitle} schema={schema} />
8090
)}
8191
</>

library/src/containers/Schemas/SchemaExample.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,35 @@ import { SCHEMA_EXAMPLE_TEXT } from '../../constants';
88

99
interface Props {
1010
title?: string;
11-
schema: Schema;
11+
schema?: Schema;
12+
example?: object;
1213
}
1314

1415
export const SchemaExampleComponent: React.FunctionComponent<Props> = ({
1516
title,
1617
schema,
18+
example,
1719
}) => {
18-
const example = JSON.stringify(
19-
schema.example ? schema.example : generateExampleSchema(schema),
20-
null,
21-
2,
22-
);
20+
const schemaExample =
21+
schema && schema.example
22+
? schema.example
23+
: schema && generateExampleSchema(schema);
24+
const exampleString = JSON.stringify(example || schemaExample || '', null, 2);
2325

24-
if (!example) {
26+
if (!exampleString) {
2527
return null;
2628
}
2729

2830
return (
2931
<div className={bemClasses.element(`schema-example`)}>
3032
<CodeComponent
31-
code={example}
33+
code={exampleString}
3234
title={
3335
<div className={bemClasses.element(`schema-example-header`)}>
3436
<span className={bemClasses.element(`schema-example-header-title`)}>
3537
{title ? title : SCHEMA_EXAMPLE_TEXT}
3638
</span>
37-
{schema.example ? null : (
39+
{example || (schema && schema.example) ? null : (
3840
<div
3941
className={bemClasses.element(
4042
`schema-example-header-generated-badge`,
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { getExamplesFromSpec } from '../getExamplesFromSpec';
2+
3+
describe('getExamplesFromSpec', () => {
4+
test('should return headers', () => {
5+
const result = getExamplesFromSpec(
6+
[
7+
{
8+
headers: {
9+
header1: 1,
10+
},
11+
payload: {
12+
prop1: 1,
13+
},
14+
},
15+
{
16+
headers: {
17+
header2: 2,
18+
},
19+
payload: {
20+
prop2: 2,
21+
},
22+
},
23+
],
24+
'headers',
25+
);
26+
expect(result).toEqual([
27+
{
28+
header1: 1,
29+
},
30+
{
31+
header2: 2,
32+
},
33+
]);
34+
});
35+
36+
test('should return payload', () => {
37+
const result = getExamplesFromSpec(
38+
[
39+
{
40+
headers: {
41+
header1: 1,
42+
},
43+
payload: {
44+
prop1: 1,
45+
},
46+
},
47+
{
48+
headers: {
49+
header2: 2,
50+
},
51+
payload: {
52+
prop2: 2,
53+
},
54+
},
55+
],
56+
'payload',
57+
);
58+
expect(result).toEqual([
59+
{
60+
prop1: 1,
61+
},
62+
{
63+
prop2: 2,
64+
},
65+
]);
66+
});
67+
68+
test('should return payload and no undefined', () => {
69+
const result = getExamplesFromSpec(
70+
[
71+
{
72+
headers: {
73+
header1: 1,
74+
},
75+
payload: {
76+
prop1: 1,
77+
},
78+
},
79+
{
80+
headers: {
81+
header2: 2,
82+
},
83+
},
84+
],
85+
'payload',
86+
);
87+
expect(result).toEqual([
88+
{
89+
prop1: 1,
90+
},
91+
]);
92+
});
93+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { Example } from '../types';
2+
3+
export type Type = 'payload' | 'headers';
4+
5+
export const getExamplesFromSpec = (examples: Example[], type: Type) =>
6+
(examples.map(el => el[type]).filter(Boolean) as any) as object[];

library/src/helpers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export * from './stateHelpers';
1010
export * from './parser';
1111
export * from './removeSpecialChars';
1212
export * from './toKebabCase';
13+
export * from './getExamplesFromSpec';

library/src/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ export interface RawMessage {
209209
description?: DescriptionHTML;
210210
externalDocs?: ExternalDocs;
211211
deprecated?: boolean;
212-
examples?: any[];
212+
examples?: Example[];
213213
protocolInfo?: any;
214214
traits?: MessageTrait | [MessageTrait, any];
215215
}
@@ -242,10 +242,15 @@ export interface MessageTrait {
242242
description?: DescriptionHTML;
243243
externalDocs?: ExternalDocs;
244244
deprecated?: boolean;
245-
examples?: any[];
245+
examples?: Example[];
246246
protocolInfo?: Record<string, any>;
247247
}
248248

249+
export interface Example {
250+
headers?: object;
251+
payload?: object;
252+
}
253+
249254
export interface Components {
250255
schemas?: Record<string, Schema>;
251256
messages?: Record<string, Message>;

0 commit comments

Comments
 (0)