Files
gitbook/packages/react-openapi/src/OpenAPISpec.tsx
T
Samy Pessé 85ec1884e6 OpenAPI blocks (#74)
* Start methods to resolve refs

* bun

* Start package

* Add code to resolve ref

* Continue

* Deref

* Start monorepo

* Continue

* Fix ref resolver

* Style a bit more

* Start toggling section

* Continue

* Start displaying query/path/headers params

* Hide respo se if empty

* Fix recursive refs

* Simplify interactive and styling

* Display enums

* Format

* Improve type name being displayed

* Improve naming

* Render oneOf/anyOf/allOf

* Handle circular references

* Start variable in server url

* Use client component for the spec part

* Improve CSS sizing

* Display open api blocks in aside

* Make aside an overlay

* Improve stickiness of openapi

* Align document on the left when api page

* Improve general layout

* Better align

* Fix padding in aside

* Use syntax highlighting

* Show sample of response

* Improve code generation

* Improve code generated

* Format

* Format

* Rename to OpenAPI

* Skip deprecated properties and handle additionalProperties

* Use discriminator for naming

* Better name enum

* Make entire header toggeable

* Format and lint

* Add curl example

* Improve curl

* style pass

* Start securities

* Bun

* Fix TS

* Improve label

* Start markdown

* Improve code samples

* Test

* Use custom skeleton for api block

* Format

* Add support for redocly code samples

* Fix api blocks in aside

* Use typography for markdown

* Format

* Fix spacing in markdown

* Render headers

* Format

* Format

---------

Co-authored-by: Sebastian Graz <graz@live.se>
2024-01-30 10:15:58 +01:00

111 lines
3.7 KiB
TypeScript

'use client';
import { OpenAPIV3 } from 'openapi-types';
import { InteractiveSection } from './InteractiveSection';
import { OpenAPIRequestBody } from './OpenAPIRequestBody';
import { OpenAPIResponses } from './OpenAPIResponses';
import { OpenAPISchemaProperties } from './OpenAPISchema';
import { OpenAPIOperationData, fromJSON } from './fetchOpenAPIOperation';
import { OpenAPIClientContext } from './types';
import { noReference } from './utils';
import { OpenAPISecurities } from './OpenAPISecurities';
/**
* Client component to render the spec for the request and response.
*
* We use a client component as rendering recursive JSON schema in the server is expensive
* (the entire schema is rendered at once, while the client component only renders the visible part)
*/
export function OpenAPISpec(props: { rawData: any; context: OpenAPIClientContext }) {
const { rawData, context } = props;
const { operation, securities } = fromJSON(rawData) as OpenAPIOperationData;
const parameterGroups = groupParameters((operation.parameters || []).map(noReference));
return (
<>
{securities.length > 0 ? (
<OpenAPISecurities securities={securities} context={context} />
) : null}
{parameterGroups.map((group) => (
<InteractiveSection
key={group.key}
className="openapi-parameters"
toggeable
toggleOpenIcon={context.icons.chevronRight}
toggleCloseIcon={context.icons.chevronDown}
header={group.label}
defaultOpened={group.key === 'path'}
>
<OpenAPISchemaProperties
properties={group.parameters.map((parameter) => ({
propertyName: parameter.name,
schema: noReference(parameter.schema) ?? {},
required: parameter.required,
}))}
context={context}
/>
</InteractiveSection>
))}
{operation.requestBody ? (
<OpenAPIRequestBody
requestBody={noReference(operation.requestBody)}
context={context}
/>
) : null}
{operation.responses ? (
<OpenAPIResponses responses={noReference(operation.responses)} context={context} />
) : null}
</>
);
}
function groupParameters(parameters: OpenAPIV3.ParameterObject[]): Array<{
key: string;
label: string;
parameters: OpenAPIV3.ParameterObject[];
}> {
const sorted = ['path', 'query', 'header'];
const groups: Array<{
key: string;
label: string;
parameters: OpenAPIV3.ParameterObject[];
}> = [];
parameters.forEach((parameter) => {
const key = parameter.in;
const label = getParameterGroupName(parameter.in);
const group = groups.find((group) => group.key === key);
if (group) {
group.parameters.push(parameter);
} else {
groups.push({
key,
label,
parameters: [parameter],
});
}
});
groups.sort((a, b) => sorted.indexOf(a.key) - sorted.indexOf(b.key));
return groups;
}
function getParameterGroupName(paramIn: string): string {
switch (paramIn) {
case 'path':
return 'Path parameters';
case 'query':
return 'Query parameters';
case 'header':
return 'Header parameters';
default:
return paramIn;
}
}