Skip to content

Commit 3968569

Browse files
committed
Update webhook block
1 parent f9c08ab commit 3968569

14 files changed

+26206
-5348
lines changed

bun.lock

+25,946-5,297
Large diffs are not rendered by default.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"@codemirror/state": "6.4.1",
1313
"react": "18.3.1",
1414
"react-dom": "18.3.1",
15-
"@gitbook/api": "0.109.0"
15+
"@gitbook/api": "0.110.0"
1616
},
1717
"private": true,
1818
"scripts": {

packages/cache-tags/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
},
1111
"version": "0.3.1",
1212
"dependencies": {
13-
"@gitbook/api": "^0.109.0",
13+
"@gitbook/api": "^0.110.0",
1414
"assert-never": "^1.2.1"
1515
},
1616
"devDependencies": {

packages/gitbook/src/lib/openapi/resolveOpenAPIWebhookBlock.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async function baseResolveOpenAPIWebhookBlock(
3434
args: ResolveOpenAPIBlockArgs<OpenAPIWebhookBlock>
3535
): Promise<ResolveOpenAPIWebhookBlockResult> {
3636
const { context, block } = args;
37-
if (!block.data.path || !block.data.method) {
37+
if (!block.data.name || !block.data.method) {
3838
return { data: null, specUrl: null };
3939
}
4040

packages/gitbook/src/lib/openapi/types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type {
22
DocumentBlockOpenAPI,
33
DocumentBlockOpenAPIOperation,
44
DocumentBlockOpenAPISchemas,
5-
// DocumentBlockOpenAPIWebhook,
5+
DocumentBlockOpenAPIWebhook,
66
} from '@gitbook/api';
77
import type { Filesystem, OpenAPIParseError, OpenAPIV3xDocument } from '@gitbook/openapi-parser';
88
import type { GitBookAnyContext } from '@v2/lib/context';
@@ -20,7 +20,7 @@ export type OpenAPISchemasBlock = DocumentBlockOpenAPISchemas;
2020
/**
2121
* Type for OpenAPI Webhook block
2222
*/
23-
export type OpenAPIWebhookBlock = any; //DocumentBlockOpenAPIWebhook
23+
export type OpenAPIWebhookBlock = DocumentBlockOpenAPIWebhook;
2424

2525
/**
2626
* Arguments for resolving OpenAPI block.

packages/react-openapi/src/OpenAPICodeSample.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function OpenAPICodeSample(props: {
2222
data: OpenAPIOperationData;
2323
context: OpenAPIContext;
2424
}) {
25-
const { data } = props;
25+
const { data, context } = props;
2626

2727
// If code samples are disabled at operation level, we don't display the code samples.
2828
if (data.operation['x-codeSamples'] === false) {
@@ -43,7 +43,9 @@ export function OpenAPICodeSample(props: {
4343
return null;
4444
}
4545

46-
return <OpenAPICodeSampleBody data={data} items={samples} />;
46+
return (
47+
<OpenAPICodeSampleBody data={data} items={samples} selectIcon={context.icons.chevronDown} />
48+
);
4749
}
4850

4951
/**
@@ -146,6 +148,7 @@ function generateCodeSamples(props: {
146148
method={data.method}
147149
path={data.path}
148150
renderers={renderers}
151+
blockKey={context.blockKey}
149152
/>
150153
),
151154
footer: (
@@ -207,6 +210,7 @@ function OpenAPICodeSampleFooter(props: {
207210
path={data.path}
208211
renderers={renderers}
209212
selectIcon={context.icons.chevronDown}
213+
blockKey={context.blockKey}
210214
/>
211215
) : (
212216
<span />

packages/react-openapi/src/OpenAPICodeSampleInteractive.tsx

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@
22
import clsx from 'clsx';
33
import type { MediaTypeRenderer } from './OpenAPICodeSample';
44
import { OpenAPISelect, OpenAPISelectItem, useSelectState } from './OpenAPISelect';
5+
import { createStateKey } from './utils';
56

67
export function OpenAPIMediaTypeExamplesSelector(props: {
78
method: string;
89
path: string;
910
renderers: MediaTypeRenderer[];
1011
selectIcon?: React.ReactNode;
12+
blockKey?: string;
1113
}) {
12-
const { method, path, renderers, selectIcon } = props;
14+
const { method, path, renderers, selectIcon, blockKey } = props;
1315
if (!renderers[0]) {
1416
throw new Error('No renderers provided');
1517
}
16-
const stateKey = `media-type-${method}-${path}`;
18+
const stateKey = createStateKey('request-body-media-type', blockKey);
1719
const state = useSelectState(stateKey, renderers[0].mediaType);
1820
const selected = renderers.find((r) => r.mediaType === state.key) || renderers[0];
1921

@@ -102,13 +104,17 @@ export function OpenAPIMediaTypeExamplesBody(props: {
102104
method: string;
103105
path: string;
104106
renderers: MediaTypeRenderer[];
107+
blockKey?: string;
105108
}) {
106-
const { renderers, method, path } = props;
109+
const { renderers, method, path, blockKey } = props;
107110
if (!renderers[0]) {
108111
throw new Error('No renderers provided');
109112
}
110113

111-
const mediaTypeState = useSelectState(`media-type-${method}-${path}`, renderers[0].mediaType);
114+
const mediaTypeState = useSelectState(
115+
createStateKey('request-body-media-type', blockKey),
116+
renderers[0].mediaType
117+
);
112118
const selected = renderers.find((r) => r.mediaType === mediaTypeState.key) ?? renderers[0];
113119
if (selected.examples.length === 0) {
114120
return selected.element;

packages/react-openapi/src/OpenAPIRequestBody.tsx

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
11
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
22
import { InteractiveSection } from './InteractiveSection';
33
import { OpenAPIRootSchema } from './OpenAPISchemaServer';
4-
import type { OpenAPIClientContext, OpenAPIOperationData } from './types';
5-
import { checkIsReference } from './utils';
4+
import type { OpenAPIClientContext, OpenAPIOperationData, OpenAPIWebhookData } from './types';
5+
import { checkIsReference, createStateKey } from './utils';
66

77
/**
88
* Display an interactive request body.
99
*/
1010
export function OpenAPIRequestBody(props: {
1111
requestBody: OpenAPIV3.RequestBodyObject | OpenAPIV3.ReferenceObject;
1212
context: OpenAPIClientContext;
13-
data: OpenAPIOperationData;
13+
data: OpenAPIOperationData | OpenAPIWebhookData;
1414
}) {
1515
const { requestBody, context, data } = props;
16-
const { method, path } = data;
1716

1817
if (checkIsReference(requestBody)) {
1918
return null;
2019
}
2120

21+
const header = 'name' in data ? 'Payload' : 'Body';
22+
2223
return (
2324
<InteractiveSection
24-
header="Body"
25+
header={header}
2526
className="openapi-requestbody"
26-
stateKey={`media-type-${method}-${path}`}
27+
stateKey={createStateKey('request-body-media-type', context.blockKey)}
2728
selectIcon={context.icons.chevronDown}
2829
tabs={Object.entries(requestBody.content ?? {}).map(
2930
([contentType, mediaTypeObject]) => {

packages/react-openapi/src/OpenAPIResponseExample.tsx

+3-18
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ import {
88
} from './OpenAPIExample';
99
import { OpenAPIResponseExampleContent } from './OpenAPIResponseExampleContent';
1010
import { OpenAPIResponseMediaTypeContent } from './OpenAPIResponseMediaType';
11-
import type { OpenAPIContext, OpenAPIOperationData } from './types';
12-
import { getStatusCodeDefaultLabel } from './utils';
11+
import type { OpenAPIContext, OpenAPIOperationData, OpenAPIWebhookData } from './types';
12+
import { getStatusCodeDefaultLabel, getSyntaxFromMediaType } from './utils';
1313
import { checkIsReference, resolveDescription } from './utils';
1414

1515
/**
1616
* Display an example of the response content.
1717
*/
1818
export function OpenAPIResponseExample(props: {
19-
data: OpenAPIOperationData;
19+
data: OpenAPIOperationData | OpenAPIWebhookData;
2020
context: OpenAPIContext;
2121
}) {
2222
const { data, context } = props;
@@ -154,18 +154,3 @@ function getExamples(props: {
154154
};
155155
});
156156
}
157-
158-
/**
159-
* Get the syntax from a media type.
160-
*/
161-
function getSyntaxFromMediaType(mediaType: string): string {
162-
if (mediaType.includes('json')) {
163-
return 'json';
164-
}
165-
166-
if (mediaType === 'application/xml') {
167-
return 'xml';
168-
}
169-
170-
return 'text';
171-
}

packages/react-openapi/src/OpenAPIWebhook.tsx

+2-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import clsx from 'clsx';
2-
import { OpenAPIExample, getExampleFromSchema } from './OpenAPIExample';
32
import { OpenAPIColumnSpec } from './common/OpenAPIColumnSpec';
43
import { OpenAPISummary } from './common/OpenAPISummary';
54
import type { OpenAPIContext, OpenAPIWebhookData } from './types';
5+
import { OpenAPIWebhookExample } from './webhook/OpenAPIWebhookExample';
66

77
/**
88
* Display an interactive OpenAPI webhook.
@@ -13,7 +13,6 @@ export function OpenAPIWebhook(props: {
1313
context: OpenAPIContext;
1414
}) {
1515
const { className, data, context } = props;
16-
const { operation } = data;
1716

1817
return (
1918
<div className={clsx('openapi-webhook', className)}>
@@ -22,18 +21,7 @@ export function OpenAPIWebhook(props: {
2221
<OpenAPIColumnSpec data={data} context={context} />
2322
<div className="openapi-column-preview">
2423
<div className="openapi-column-preview-body">
25-
<div className="openapi-panel">
26-
<h4 className="openapi-panel-heading">Payload</h4>
27-
<div className="openapi-panel-body">
28-
<OpenAPIExample
29-
example={getExampleFromSchema({
30-
schema: operation.schema,
31-
})}
32-
context={context}
33-
syntax="json"
34-
/>
35-
</div>
36-
</div>
24+
<OpenAPIWebhookExample data={data} context={context} />
3725
</div>
3826
</div>
3927
</div>

packages/react-openapi/src/common/OpenAPISummary.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export function OpenAPISummary(props: {
99
const { data, context } = props;
1010
const { operation } = data;
1111

12+
const title = 'name' in data ? data.name : operation.summary;
13+
1214
return (
1315
<div className="openapi-summary" id={operation.summary ? undefined : context.id}>
1416
{(operation.deprecated || operation['x-stability']) && (
@@ -19,11 +21,11 @@ export function OpenAPISummary(props: {
1921
)}
2022
</div>
2123
)}
22-
{operation.summary
24+
{title
2325
? context.renderHeading({
2426
deprecated: operation.deprecated ?? false,
2527
stability: operation['x-stability'],
26-
title: operation.summary,
28+
title: title,
2729
})
2830
: null}
2931
{'path' in data ? <OpenAPIPath data={data} /> : null}

packages/react-openapi/src/utils.ts

+15
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,18 @@ function getStatusCodeCategory(statusCode: number | string): number | string {
211211

212212
return category;
213213
}
214+
215+
/**
216+
* Get the syntax from a media type.
217+
*/
218+
export function getSyntaxFromMediaType(mediaType: string): string {
219+
if (mediaType.includes('json')) {
220+
return 'json';
221+
}
222+
223+
if (mediaType === 'application/xml') {
224+
return 'xml';
225+
}
226+
227+
return 'text';
228+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2+
import { OpenAPIEmptyExample, OpenAPIExample, getExampleFromSchema } from '../OpenAPIExample';
3+
import type { OpenAPIContext } from '../types';
4+
import type { OpenAPIWebhookData } from '../types';
5+
import { getSyntaxFromMediaType } from '../utils';
6+
import { OpenAPIResponseMediaTypeContent } from './OpenAPIWebhookExampleContent';
7+
8+
export function OpenAPIWebhookExample(props: {
9+
data: OpenAPIWebhookData;
10+
context: OpenAPIContext;
11+
}) {
12+
const { data, context } = props;
13+
const { operation } = data;
14+
15+
const items = (() => {
16+
if (!operation.requestBody) {
17+
return [];
18+
}
19+
20+
return Object.entries(
21+
operation.requestBody.content as Record<string, OpenAPIV3.MediaTypeObject>
22+
).map(([key, value]) => {
23+
const schema = value.schema;
24+
const syntax = getSyntaxFromMediaType(key);
25+
26+
if (!schema) {
27+
return {
28+
key,
29+
label: key,
30+
body: <OpenAPIEmptyExample />,
31+
};
32+
}
33+
34+
return {
35+
key,
36+
label: key,
37+
body: (
38+
<OpenAPIExample
39+
context={context}
40+
example={getExampleFromSchema({ schema })}
41+
syntax={syntax}
42+
/>
43+
),
44+
};
45+
});
46+
})();
47+
48+
return (
49+
<div className="openapi-panel">
50+
<h4 className="openapi-panel-heading">Payload</h4>
51+
<div className="openapi-panel-body">
52+
<OpenAPIResponseMediaTypeContent
53+
items={items}
54+
selectIcon={context.icons.chevronDown}
55+
blockKey={context.blockKey}
56+
/>
57+
</div>
58+
</div>
59+
);
60+
}

0 commit comments

Comments
 (0)