@gitbook/react-openapi 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/InteractiveSection.js +59 -0
- package/dist/Markdown.js +10 -0
- package/dist/OpenAPICodeSample.js +219 -0
- package/dist/OpenAPICodeSampleInteractive.js +66 -0
- package/dist/OpenAPICodeSampleSelector.js +45 -0
- package/dist/OpenAPICopyButton.js +39 -0
- package/dist/OpenAPIDisclosure.js +30 -0
- package/dist/OpenAPIDisclosureGroup.js +75 -0
- package/dist/OpenAPIExample.js +41 -0
- package/dist/OpenAPIMediaType.js +58 -0
- package/dist/OpenAPIOperation.d.ts +15 -0
- package/dist/OpenAPIOperation.js +30 -0
- package/dist/OpenAPIOperationContext.d.ts +20 -0
- package/dist/OpenAPIOperationContext.js +30 -0
- package/dist/OpenAPIPath.js +51 -0
- package/dist/OpenAPIPrefillContextProvider.d.ts +26 -0
- package/dist/OpenAPIPrefillContextProvider.js +25 -0
- package/dist/OpenAPIRequestBody.js +28 -0
- package/dist/OpenAPIRequestBodyHeaderType.js +23 -0
- package/dist/OpenAPIResponse.js +39 -0
- package/dist/OpenAPIResponseExample.js +75 -0
- package/dist/OpenAPIResponseExampleContent.js +61 -0
- package/dist/OpenAPIResponses.js +61 -0
- package/dist/OpenAPISchema.js +373 -0
- package/dist/OpenAPISchemaName.js +45 -0
- package/dist/OpenAPISchemaServer.js +13 -0
- package/dist/OpenAPISecurities.js +124 -0
- package/dist/OpenAPISelect.js +45 -0
- package/dist/OpenAPISpec.js +73 -0
- package/dist/OpenAPIWebhook.d.ts +15 -0
- package/dist/OpenAPIWebhook.js +28 -0
- package/dist/OpenAPIWebhookExample.js +40 -0
- package/dist/ScalarApiButton.js +87 -0
- package/dist/StaticSection.js +37 -0
- package/dist/code-samples.js +275 -0
- package/dist/common/OpenAPIColumnSpec.js +23 -0
- package/dist/common/OpenAPIOperationDescription.js +18 -0
- package/dist/common/OpenAPIStability.js +17 -0
- package/dist/common/OpenAPISummary.js +27 -0
- package/dist/contentTypeChecks.js +34 -0
- package/dist/context.d.ts +71 -0
- package/dist/context.js +29 -0
- package/dist/decycle.js +41 -0
- package/dist/dereference.js +24 -0
- package/dist/generateSchemaExample.js +198 -0
- package/dist/getDisclosureLabel.js +17 -0
- package/dist/getOrCreateStoreByKey.js +22 -0
- package/dist/index.d.ts +11 -662
- package/dist/index.js +9 -3871
- package/dist/json2xml.js +12 -0
- package/dist/resolveOpenAPIOperation.d.ts +15 -0
- package/dist/resolveOpenAPIOperation.js +102 -0
- package/dist/resolveOpenAPIWebhook.d.ts +15 -0
- package/dist/resolveOpenAPIWebhook.js +52 -0
- package/dist/schemas/OpenAPISchemaItem.js +26 -0
- package/dist/schemas/OpenAPISchemas.d.ts +19 -0
- package/dist/schemas/OpenAPISchemas.js +57 -0
- package/dist/schemas/resolveOpenAPISchemas.d.ts +15 -0
- package/dist/schemas/resolveOpenAPISchemas.js +17 -0
- package/dist/stringifyOpenAPI.js +14 -0
- package/dist/translate.js +43 -0
- package/dist/translations/de.js +48 -0
- package/dist/translations/en.d.ts +47 -0
- package/dist/translations/en.js +48 -0
- package/dist/translations/es.js +48 -0
- package/dist/translations/fr.js +48 -0
- package/dist/translations/index.d.ts +408 -0
- package/dist/translations/index.js +31 -0
- package/dist/translations/ja.js +48 -0
- package/dist/translations/nl.js +48 -0
- package/dist/translations/no.js +48 -0
- package/dist/translations/pt-br.js +48 -0
- package/dist/translations/types.d.ts +7 -0
- package/dist/translations/zh.js +48 -0
- package/dist/types.d.ts +37 -0
- package/dist/util/example.js +84 -0
- package/dist/util/server.js +38 -0
- package/dist/util/tryit-prefill.js +143 -0
- package/dist/utils.js +163 -0
- package/package.json +10 -7
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { OpenAPIContextInput } from "./context.js";
|
|
2
|
+
import { OpenAPIOperationData } from "./types.js";
|
|
3
|
+
import * as react0 from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/OpenAPIOperation.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Display an interactive OpenAPI operation.
|
|
8
|
+
*/
|
|
9
|
+
declare function OpenAPIOperation(props: {
|
|
10
|
+
className?: string;
|
|
11
|
+
data: OpenAPIOperationData;
|
|
12
|
+
context: OpenAPIContextInput;
|
|
13
|
+
}): react0.JSX.Element;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { OpenAPIOperation };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { resolveOpenAPIContext } from "./context.js";
|
|
2
|
+
import { OpenAPICodeSample } from "./OpenAPICodeSample.js";
|
|
3
|
+
import { OpenAPIResponseExample } from "./OpenAPIResponseExample.js";
|
|
4
|
+
import { OpenAPIColumnSpec } from "./common/OpenAPIColumnSpec.js";
|
|
5
|
+
import { OpenAPISummary } from "./common/OpenAPISummary.js";
|
|
6
|
+
import clsx from "classnames";
|
|
7
|
+
|
|
8
|
+
//#region src/OpenAPIOperation.tsx
|
|
9
|
+
/**
|
|
10
|
+
* Display an interactive OpenAPI operation.
|
|
11
|
+
*/
|
|
12
|
+
function OpenAPIOperation(props) {
|
|
13
|
+
const { className, data, context: contextInput } = props;
|
|
14
|
+
const context = resolveOpenAPIContext(contextInput);
|
|
15
|
+
return <div className={clsx("openapi-operation", className)}>
|
|
16
|
+
<OpenAPISummary data={data} context={context} />
|
|
17
|
+
<div className="openapi-columns">
|
|
18
|
+
<OpenAPIColumnSpec data={data} context={context} />
|
|
19
|
+
<div className="openapi-column-preview">
|
|
20
|
+
<div className="openapi-column-preview-body">
|
|
21
|
+
<OpenAPICodeSample data={data} context={context} />
|
|
22
|
+
<OpenAPIResponseExample data={data} context={context} />
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { OpenAPIOperation };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as react1 from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/OpenAPIOperationContext.d.ts
|
|
4
|
+
interface OpenAPIOperationPointer {
|
|
5
|
+
path: string;
|
|
6
|
+
method: string;
|
|
7
|
+
}
|
|
8
|
+
interface OpenAPIOperationContextValue {
|
|
9
|
+
onOpenClient: (pointer: OpenAPIOperationPointer) => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Provider for the OpenAPIOperationContext.
|
|
13
|
+
*/
|
|
14
|
+
declare function OpenAPIOperationContextProvider(props: React.PropsWithChildren<Partial<OpenAPIOperationContextValue>>): react1.JSX.Element;
|
|
15
|
+
/**
|
|
16
|
+
* Hook to access the OpenAPIOperationContext.
|
|
17
|
+
*/
|
|
18
|
+
declare function useOpenAPIOperationContext(): OpenAPIOperationContextValue;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { OpenAPIOperationContextProvider, useOpenAPIOperationContext };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { createContext, useContext, useMemo } from "react";
|
|
5
|
+
import { useEventCallback } from "usehooks-ts";
|
|
6
|
+
|
|
7
|
+
//#region src/OpenAPIOperationContext.tsx
|
|
8
|
+
const OpenAPIOperationContext = createContext({ onOpenClient: () => {} });
|
|
9
|
+
/**
|
|
10
|
+
* Provider for the OpenAPIOperationContext.
|
|
11
|
+
*/
|
|
12
|
+
function OpenAPIOperationContextProvider(props) {
|
|
13
|
+
const { children } = props;
|
|
14
|
+
const onOpenClient = useEventCallback((pointer) => {
|
|
15
|
+
props.onOpenClient?.(pointer);
|
|
16
|
+
});
|
|
17
|
+
const value = useMemo(() => ({ onOpenClient }), [onOpenClient]);
|
|
18
|
+
return <OpenAPIOperationContext.Provider value={value}>
|
|
19
|
+
{children}
|
|
20
|
+
</OpenAPIOperationContext.Provider>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Hook to access the OpenAPIOperationContext.
|
|
24
|
+
*/
|
|
25
|
+
function useOpenAPIOperationContext() {
|
|
26
|
+
return useContext(OpenAPIOperationContext);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { OpenAPIOperationContextProvider, useOpenAPIOperationContext };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { OpenAPICopyButton } from "./OpenAPICopyButton.js";
|
|
2
|
+
import { getOpenAPIClientContext } from "./context.js";
|
|
3
|
+
import { getDefaultServerURL } from "./util/server.js";
|
|
4
|
+
|
|
5
|
+
//#region src/OpenAPIPath.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Display the path of an operation.
|
|
8
|
+
*/
|
|
9
|
+
function OpenAPIPath(props) {
|
|
10
|
+
const { data, context, withServer = true, canCopy = true } = props;
|
|
11
|
+
const { method, path, operation } = data;
|
|
12
|
+
const server = getDefaultServerURL(data.servers);
|
|
13
|
+
const formattedPath = formatPath(path);
|
|
14
|
+
const element = (() => {
|
|
15
|
+
return <>
|
|
16
|
+
{withServer ? <span className="openapi-path-server">{server}</span> : null}
|
|
17
|
+
{formattedPath}
|
|
18
|
+
</>;
|
|
19
|
+
})();
|
|
20
|
+
return <div className="openapi-path">
|
|
21
|
+
<div className={`openapi-method openapi-method-${method}`}>{method}</div>
|
|
22
|
+
|
|
23
|
+
<OpenAPICopyButton value={`${withServer ? server : ""}${path}`} className="openapi-path-title" data-deprecated={operation.deprecated} isDisabled={!canCopy} context={getOpenAPIClientContext(context)}>
|
|
24
|
+
{element}
|
|
25
|
+
</OpenAPICopyButton>
|
|
26
|
+
</div>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Format the path by wrapping placeholders in <span> tags.
|
|
30
|
+
*/
|
|
31
|
+
function formatPath(path) {
|
|
32
|
+
const regex = /\{\s*(\w+)\s*\}|:\w+/g;
|
|
33
|
+
const parts = [];
|
|
34
|
+
let lastIndex = 0;
|
|
35
|
+
path.replace(regex, (match, _, offset) => {
|
|
36
|
+
if (offset > lastIndex) parts.push(path.slice(lastIndex, offset));
|
|
37
|
+
parts.push(<span key={`offset-${offset}`} className="openapi-path-variable">
|
|
38
|
+
{match}
|
|
39
|
+
</span>);
|
|
40
|
+
lastIndex = offset + match.length;
|
|
41
|
+
return match;
|
|
42
|
+
});
|
|
43
|
+
if (lastIndex < path.length) parts.push(path.slice(lastIndex));
|
|
44
|
+
return parts.map((part, index) => {
|
|
45
|
+
if (typeof part === "string") return <span key={`part-${index}`}>{part}</span>;
|
|
46
|
+
return part;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
export { OpenAPIPath };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React$1 from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/OpenAPIPrefillContextProvider.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Prefill data that can be used to dynamically inject info into OpenAPI operation blocks.
|
|
7
|
+
*
|
|
8
|
+
* This is typically dynamic input context, such as visitor data or environment info.
|
|
9
|
+
*/
|
|
10
|
+
type PrefillInputContextData = Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Context value is function that returns prefill data.
|
|
13
|
+
*/
|
|
14
|
+
type PrefillContextValue = () => PrefillInputContextData | null;
|
|
15
|
+
/**
|
|
16
|
+
* Provide context to help prefill dynamic info like visitor data in OpenAPI blocks.
|
|
17
|
+
*/
|
|
18
|
+
declare function OpenAPIPrefillContextProvider(props: React$1.PropsWithChildren<{
|
|
19
|
+
getPrefillInputContextData: () => PrefillInputContextData | null;
|
|
20
|
+
}>): React$1.JSX.Element;
|
|
21
|
+
/**
|
|
22
|
+
* Hook to access the prefill context function.
|
|
23
|
+
*/
|
|
24
|
+
declare function useOpenAPIPrefillContext(): PrefillContextValue;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { OpenAPIPrefillContextProvider, PrefillInputContextData, useOpenAPIPrefillContext };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import * as React$1 from "react";
|
|
5
|
+
|
|
6
|
+
//#region src/OpenAPIPrefillContextProvider.tsx
|
|
7
|
+
const OpenAPIPrefillContext = React$1.createContext(null);
|
|
8
|
+
/**
|
|
9
|
+
* Provide context to help prefill dynamic info like visitor data in OpenAPI blocks.
|
|
10
|
+
*/
|
|
11
|
+
function OpenAPIPrefillContextProvider(props) {
|
|
12
|
+
const { getPrefillInputContextData, children } = props;
|
|
13
|
+
return <OpenAPIPrefillContext.Provider value={getPrefillInputContextData}>
|
|
14
|
+
{children}
|
|
15
|
+
</OpenAPIPrefillContext.Provider>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Hook to access the prefill context function.
|
|
19
|
+
*/
|
|
20
|
+
function useOpenAPIPrefillContext() {
|
|
21
|
+
return React$1.useContext(OpenAPIPrefillContext) ?? (() => null);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { OpenAPIPrefillContextProvider, useOpenAPIPrefillContext };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { t } from "./translate.js";
|
|
2
|
+
import { checkIsReference, createStateKey } from "./utils.js";
|
|
3
|
+
import { OpenAPIRootSchema } from "./OpenAPISchemaServer.js";
|
|
4
|
+
import { InteractiveSection } from "./InteractiveSection.js";
|
|
5
|
+
import { OpenAPIRequestBodyHeaderType } from "./OpenAPIRequestBodyHeaderType.js";
|
|
6
|
+
|
|
7
|
+
//#region src/OpenAPIRequestBody.tsx
|
|
8
|
+
/**
|
|
9
|
+
* Display an interactive request body.
|
|
10
|
+
*/
|
|
11
|
+
function OpenAPIRequestBody(props) {
|
|
12
|
+
const { requestBody, context, data } = props;
|
|
13
|
+
if (checkIsReference(requestBody)) return null;
|
|
14
|
+
const stateKey = createStateKey("request-body-media-type", context.blockKey);
|
|
15
|
+
return <InteractiveSection header={<>
|
|
16
|
+
<span>{t(context.translation, "name" in data ? "payload" : "body")}</span>
|
|
17
|
+
<OpenAPIRequestBodyHeaderType requestBody={requestBody} stateKey={stateKey} />
|
|
18
|
+
</>} className="openapi-requestbody" stateKey={stateKey} selectIcon={context.icons.chevronDown} tabs={Object.entries(requestBody.content ?? {}).map(([contentType, mediaTypeObject]) => {
|
|
19
|
+
return {
|
|
20
|
+
key: contentType,
|
|
21
|
+
label: contentType,
|
|
22
|
+
body: <OpenAPIRootSchema schema={mediaTypeObject.schema ?? {}} context={context} key={contentType} />
|
|
23
|
+
};
|
|
24
|
+
})} />;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
export { OpenAPIRequestBody };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { getSchemaTitle } from "./utils.js";
|
|
5
|
+
import { useSelectState } from "./OpenAPISelect.js";
|
|
6
|
+
|
|
7
|
+
//#region src/OpenAPIRequestBodyHeaderType.tsx
|
|
8
|
+
/**
|
|
9
|
+
* Display the type of a request body. It only displays the type if the selected content is an array.
|
|
10
|
+
*/
|
|
11
|
+
function OpenAPIRequestBodyHeaderType(props) {
|
|
12
|
+
const { requestBody, stateKey } = props;
|
|
13
|
+
const content = requestBody.content ?? {};
|
|
14
|
+
const state = useSelectState(stateKey, Object.keys(content)[0]);
|
|
15
|
+
const selectedContentMediaType = Object.entries(content).find(([contentType]) => contentType === state.key)?.[1];
|
|
16
|
+
if (!selectedContentMediaType || !selectedContentMediaType.schema?.type || selectedContentMediaType.schema.type !== "array") return null;
|
|
17
|
+
return <span className="openapi-requestbody-header-type">
|
|
18
|
+
{`${getSchemaTitle(selectedContentMediaType.schema)}`}
|
|
19
|
+
</span>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { OpenAPIRequestBodyHeaderType };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { tString } from "./translate.js";
|
|
2
|
+
import { OpenAPIDisclosure } from "./OpenAPIDisclosure.js";
|
|
3
|
+
import { parameterToProperty, resolveDescription } from "./utils.js";
|
|
4
|
+
import { OpenAPISchemaPresentation } from "./OpenAPISchema.js";
|
|
5
|
+
import { OpenAPISchemaProperties } from "./OpenAPISchemaServer.js";
|
|
6
|
+
|
|
7
|
+
//#region src/OpenAPIResponse.tsx
|
|
8
|
+
/**
|
|
9
|
+
* Display an interactive response body.
|
|
10
|
+
*/
|
|
11
|
+
function OpenAPIResponse(props) {
|
|
12
|
+
const { response, context, mediaType } = props;
|
|
13
|
+
const headers = Object.entries(response.headers ?? {}).map(([name, header]) => [name, header ?? {}]);
|
|
14
|
+
const content = Object.entries(mediaType?.schema ?? {});
|
|
15
|
+
const description = resolveDescription(response);
|
|
16
|
+
if (content.length === 0 && !description && headers.length === 0) return null;
|
|
17
|
+
return <div className="openapi-response-body">
|
|
18
|
+
{headers.length > 0 ? <OpenAPIDisclosure header={<OpenAPISchemaPresentation context={context} property={{
|
|
19
|
+
propertyName: tString(context.translation, "headers"),
|
|
20
|
+
schema: { type: "object" },
|
|
21
|
+
required: null
|
|
22
|
+
}} />} icon={context.icons.plus} label={(isExpanded) => tString(context.translation, isExpanded ? "hide" : "show", tString(context.translation, headers.length === 1 ? "header" : "headers"))}>
|
|
23
|
+
<OpenAPISchemaProperties properties={headers.map(([name, header]) => parameterToProperty({
|
|
24
|
+
name,
|
|
25
|
+
...header
|
|
26
|
+
}))} context={context} />
|
|
27
|
+
</OpenAPIDisclosure> : null}
|
|
28
|
+
{mediaType?.schema && <div className="openapi-responsebody">
|
|
29
|
+
<OpenAPISchemaProperties id={`response-${context.blockKey}`} properties={[{
|
|
30
|
+
schema: mediaType.schema,
|
|
31
|
+
propertyName: tString(context.translation, "response"),
|
|
32
|
+
required: null
|
|
33
|
+
}]} context={context} />
|
|
34
|
+
</div>}
|
|
35
|
+
</div>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { OpenAPIResponse };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { OpenAPIEmptyExample, OpenAPIExample } from "./OpenAPIExample.js";
|
|
2
|
+
import { Markdown } from "./Markdown.js";
|
|
3
|
+
import { checkIsReference, createStateKey, getStatusCodeDefaultLabel, resolveDescription } from "./utils.js";
|
|
4
|
+
import { getOpenAPIClientContext } from "./context.js";
|
|
5
|
+
import { getExampleFromReference, getExamples } from "./util/example.js";
|
|
6
|
+
import { OpenAPIMediaTypeContent } from "./OpenAPIMediaType.js";
|
|
7
|
+
import { OpenAPIResponseExampleContent } from "./OpenAPIResponseExampleContent.js";
|
|
8
|
+
|
|
9
|
+
//#region src/OpenAPIResponseExample.tsx
|
|
10
|
+
/**
|
|
11
|
+
* Display an example of the response content.
|
|
12
|
+
*/
|
|
13
|
+
function OpenAPIResponseExample(props) {
|
|
14
|
+
const { data, context } = props;
|
|
15
|
+
if (!data.operation.responses) return null;
|
|
16
|
+
const responses = Object.entries(data.operation.responses);
|
|
17
|
+
responses.sort(([a], [b]) => {
|
|
18
|
+
if (a === "default") return 1;
|
|
19
|
+
if (b === "default") return -1;
|
|
20
|
+
if (a === "200") return -1;
|
|
21
|
+
if (b === "200") return 1;
|
|
22
|
+
return Number(a) - Number(b);
|
|
23
|
+
});
|
|
24
|
+
const tabs = responses.filter(([_, responseObject]) => responseObject && typeof responseObject === "object" && !responseObject["x-hideSample"]).map(([key, responseObject]) => {
|
|
25
|
+
const description = resolveDescription(responseObject);
|
|
26
|
+
const label = description ? <Markdown key={`response-description-${key}`} source={description} /> : getStatusCodeDefaultLabel(key, context);
|
|
27
|
+
if (checkIsReference(responseObject)) return {
|
|
28
|
+
key,
|
|
29
|
+
label,
|
|
30
|
+
statusCode: key,
|
|
31
|
+
body: <OpenAPIExample example={getExampleFromReference(responseObject, context)} context={context} syntax="json" />
|
|
32
|
+
};
|
|
33
|
+
if (!responseObject.content || Object.keys(responseObject.content).length === 0) return {
|
|
34
|
+
key,
|
|
35
|
+
label,
|
|
36
|
+
statusCode: key,
|
|
37
|
+
body: <OpenAPIEmptyExample context={context} />
|
|
38
|
+
};
|
|
39
|
+
return {
|
|
40
|
+
key,
|
|
41
|
+
label,
|
|
42
|
+
statusCode: key,
|
|
43
|
+
body: <OpenAPIResponse context={context} content={responseObject.content} />
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
if (tabs.length === 0) return null;
|
|
47
|
+
return <OpenAPIResponseExampleContent selectIcon={context.icons.chevronDown} blockKey={context.blockKey} items={tabs} />;
|
|
48
|
+
}
|
|
49
|
+
function OpenAPIResponse(props) {
|
|
50
|
+
const { context, content } = props;
|
|
51
|
+
const entries = Object.entries(content);
|
|
52
|
+
if (!entries[0]) throw new Error("One media type is required");
|
|
53
|
+
const tabs = entries.map((entry) => {
|
|
54
|
+
const [mediaType, mediaTypeObject] = entry;
|
|
55
|
+
if (!mediaTypeObject) return {
|
|
56
|
+
key: mediaType,
|
|
57
|
+
label: mediaType,
|
|
58
|
+
body: <OpenAPIEmptyExample context={context} />
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
key: mediaType,
|
|
62
|
+
label: mediaType,
|
|
63
|
+
body: <></>,
|
|
64
|
+
examples: getExamples({
|
|
65
|
+
mediaTypeObject,
|
|
66
|
+
mediaType,
|
|
67
|
+
context
|
|
68
|
+
})
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
return <OpenAPIMediaTypeContent selectIcon={context.icons.chevronDown} stateKey={createStateKey("response-media-types", context.blockKey)} items={tabs} context={getOpenAPIClientContext(context)} />;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { OpenAPIResponseExample };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { createStateKey, getStatusCodeClassName } from "./utils.js";
|
|
5
|
+
import { StaticSection } from "./StaticSection.js";
|
|
6
|
+
import { OpenAPISelect, OpenAPISelectItem, useSelectState } from "./OpenAPISelect.js";
|
|
7
|
+
import clsx from "classnames";
|
|
8
|
+
|
|
9
|
+
//#region src/OpenAPIResponseExampleContent.tsx
|
|
10
|
+
/**
|
|
11
|
+
* Get the state of the response examples select.
|
|
12
|
+
*/
|
|
13
|
+
function useResponseExamplesState(blockKey, initialKey = "default") {
|
|
14
|
+
return useSelectState(getResponseExampleStateKey(blockKey), initialKey);
|
|
15
|
+
}
|
|
16
|
+
function OpenAPIResponseExampleContent(props) {
|
|
17
|
+
const { blockKey, items, selectIcon } = props;
|
|
18
|
+
return <StaticSection header={<OpenAPIResponseExampleHeader selectIcon={selectIcon} blockKey={blockKey} items={items} />} className="openapi-response-examples">
|
|
19
|
+
<OpenAPIResponseExampleBody blockKey={blockKey} items={items} />
|
|
20
|
+
</StaticSection>;
|
|
21
|
+
}
|
|
22
|
+
function OpenAPIResponseExampleHeader(props) {
|
|
23
|
+
const { items, blockKey, selectIcon } = props;
|
|
24
|
+
if (items.length === 1) {
|
|
25
|
+
const item = items[0];
|
|
26
|
+
if (!item) return null;
|
|
27
|
+
return <span className="openapi-response-examples-statuscode-title">
|
|
28
|
+
<OpenAPIResponseExampleItem item={item} />
|
|
29
|
+
</span>;
|
|
30
|
+
}
|
|
31
|
+
return <OpenAPISelect items={items} icon={selectIcon} stateKey={getResponseExampleStateKey(blockKey)} placement="bottom start">
|
|
32
|
+
{items.map((item) => <OpenAPISelectItem key={item.key} id={item.key} value={item}>
|
|
33
|
+
<OpenAPIResponseExampleItem item={item} />
|
|
34
|
+
</OpenAPISelectItem>)}
|
|
35
|
+
</OpenAPISelect>;
|
|
36
|
+
}
|
|
37
|
+
function OpenAPIResponseExampleItem(props) {
|
|
38
|
+
const { item } = props;
|
|
39
|
+
return <>
|
|
40
|
+
<span className={clsx("openapi-statuscode", `openapi-statuscode-${getStatusCodeClassName(item.statusCode)}`, "openapi-response-examples-statuscode")}>
|
|
41
|
+
{item.statusCode}
|
|
42
|
+
</span>
|
|
43
|
+
<span className="openapi-response-examples-statuscode-label">{item.label}</span>
|
|
44
|
+
</>;
|
|
45
|
+
}
|
|
46
|
+
function OpenAPIResponseExampleBody(props) {
|
|
47
|
+
const { blockKey, items } = props;
|
|
48
|
+
const state = useResponseExamplesState(blockKey, items[0]?.key);
|
|
49
|
+
const selectedItem = items.find((item) => item.key === state.key) ?? items[0];
|
|
50
|
+
if (!selectedItem) return null;
|
|
51
|
+
return <div className="openapi-response-examples-panel">{selectedItem.body}</div>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Return the state key for the response examples.
|
|
55
|
+
*/
|
|
56
|
+
function getResponseExampleStateKey(blockKey) {
|
|
57
|
+
return createStateKey("openapi-responses", blockKey);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//#endregion
|
|
61
|
+
export { OpenAPIResponseExampleContent, useResponseExamplesState };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { t } from "./translate.js";
|
|
5
|
+
import { Markdown } from "./Markdown.js";
|
|
6
|
+
import { createStateKey, getStatusCodeClassName, getStatusCodeDefaultLabel, resolveDescription } from "./utils.js";
|
|
7
|
+
import { StaticSection } from "./StaticSection.js";
|
|
8
|
+
import { useResponseExamplesState } from "./OpenAPIResponseExampleContent.js";
|
|
9
|
+
import { OpenAPIDisclosureGroup } from "./OpenAPIDisclosureGroup.js";
|
|
10
|
+
import { OpenAPIResponse } from "./OpenAPIResponse.js";
|
|
11
|
+
import clsx from "classnames";
|
|
12
|
+
|
|
13
|
+
//#region src/OpenAPIResponses.tsx
|
|
14
|
+
/**
|
|
15
|
+
* Display an interactive response body.
|
|
16
|
+
*/
|
|
17
|
+
function OpenAPIResponses(props) {
|
|
18
|
+
const { responses, context } = props;
|
|
19
|
+
const groups = Object.entries(responses).filter(([_, response]) => response && typeof response === "object").map(([statusCode, response]) => {
|
|
20
|
+
const tabs = (() => {
|
|
21
|
+
if ((!response.content || !Object.keys(response.content).length) && response.headers && Object.keys(response.headers).length) return [{
|
|
22
|
+
key: "default",
|
|
23
|
+
label: "",
|
|
24
|
+
body: <OpenAPIResponse response={response} mediaType={{}} context={context} />
|
|
25
|
+
}];
|
|
26
|
+
if (!response.content) return [{
|
|
27
|
+
key: "default",
|
|
28
|
+
label: "",
|
|
29
|
+
body: <pre className="openapi-example-empty">
|
|
30
|
+
<p>{t(context.translation, "no_content")}</p>
|
|
31
|
+
</pre>
|
|
32
|
+
}];
|
|
33
|
+
return Object.entries(response.content ?? {}).map(([contentType, mediaType]) => ({
|
|
34
|
+
key: contentType,
|
|
35
|
+
label: contentType,
|
|
36
|
+
body: <OpenAPIResponse response={response} mediaType={mediaType} context={context} />
|
|
37
|
+
}));
|
|
38
|
+
})();
|
|
39
|
+
const description = resolveDescription(response);
|
|
40
|
+
return {
|
|
41
|
+
key: statusCode,
|
|
42
|
+
label: <div className="openapi-response-tab-content">
|
|
43
|
+
<span className={clsx("openapi-statuscode", `openapi-statuscode-${getStatusCodeClassName(statusCode)}`)}>
|
|
44
|
+
{statusCode}
|
|
45
|
+
</span>
|
|
46
|
+
{description ? <Markdown source={description} className="openapi-response-description" /> : getStatusCodeDefaultLabel(statusCode, context)}
|
|
47
|
+
</div>,
|
|
48
|
+
tabs
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
const state = useResponseExamplesState(context.blockKey, groups[0]?.key);
|
|
52
|
+
return <StaticSection header={t(context.translation, "responses")} className="openapi-responses">
|
|
53
|
+
<OpenAPIDisclosureGroup icon={context.icons.chevronRight} expandedKeys={state.key ? new Set([state.key]) : /* @__PURE__ */ new Set()} onExpandedChange={(keys) => {
|
|
54
|
+
const key = keys.values().next().value ?? null;
|
|
55
|
+
state.setKey(key);
|
|
56
|
+
}} groups={groups} selectIcon={context.icons.chevronDown} selectStateKey={createStateKey("response-media-types", context.blockKey)} />
|
|
57
|
+
</StaticSection>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//#endregion
|
|
61
|
+
export { OpenAPIResponses };
|