@gitbook/react-openapi 1.5.1 → 1.5.3
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 +27 -0
- package/dist/InteractiveSection.js +59 -0
- package/dist/Markdown.js +10 -0
- package/dist/OpenAPICodeSample.js +219 -0
- package/dist/OpenAPICodeSampleInteractive.js +62 -0
- package/dist/OpenAPICodeSampleSelector.js +45 -0
- package/dist/OpenAPICopyButton.js +44 -0
- package/dist/OpenAPIDisclosure.js +28 -0
- package/dist/OpenAPIDisclosureGroup.js +89 -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 +25 -0
- package/dist/OpenAPIPathItem.js +22 -0
- package/dist/OpenAPIPathMultipleServers.js +43 -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/OpenAPIRequiredScopes.js +67 -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 +98 -0
- package/dist/OpenAPISelect.js +45 -0
- package/dist/OpenAPISpec.js +73 -0
- package/dist/OpenAPITooltip.js +23 -0
- package/dist/OpenAPIWebhook.d.ts +15 -0
- package/dist/OpenAPIWebhook.js +28 -0
- package/dist/OpenAPIWebhookExample.js +40 -0
- package/dist/ScalarApiButton.js +90 -0
- package/dist/StaticSection.js +37 -0
- package/dist/code-samples.js +305 -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 +74 -0
- package/dist/context.js +29 -0
- package/dist/decycle.js +41 -0
- package/dist/dereference.js +24 -0
- package/dist/formatPath.js +25 -0
- package/dist/generateSchemaExample.js +198 -0
- package/dist/getDisclosureLabel.js +17 -0
- package/dist/getOrCreateDisclosureStoreByKey.js +31 -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 +105 -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 +50 -0
- package/dist/translations/en.d.ts +49 -0
- package/dist/translations/en.js +50 -0
- package/dist/translations/es.js +50 -0
- package/dist/translations/fr.js +50 -0
- package/dist/translations/index.d.ts +426 -0
- package/dist/translations/index.js +31 -0
- package/dist/translations/ja.js +50 -0
- package/dist/translations/nl.js +50 -0
- package/dist/translations/no.js +50 -0
- package/dist/translations/pt-br.js +50 -0
- package/dist/translations/types.d.ts +7 -0
- package/dist/translations/zh.js +50 -0
- package/dist/types.d.ts +38 -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 +28 -12
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { OpenAPIEmptyExample } from "./OpenAPIExample.js";
|
|
5
|
+
import { StaticSection } from "./StaticSection.js";
|
|
6
|
+
import { OpenAPISelect, OpenAPISelectItem, useSelectState } from "./OpenAPISelect.js";
|
|
7
|
+
|
|
8
|
+
//#region src/OpenAPIMediaType.tsx
|
|
9
|
+
/**
|
|
10
|
+
* Get the state of the response examples select.
|
|
11
|
+
*/
|
|
12
|
+
function useMediaTypesState(stateKey, initialKey = "default") {
|
|
13
|
+
return useSelectState(stateKey, initialKey);
|
|
14
|
+
}
|
|
15
|
+
function useMediaTypeExamplesState(stateKey, initialKey = "default") {
|
|
16
|
+
return useSelectState(stateKey, initialKey);
|
|
17
|
+
}
|
|
18
|
+
function OpenAPIMediaTypeContent(props) {
|
|
19
|
+
const { stateKey, items, selectIcon, context } = props;
|
|
20
|
+
const state = useMediaTypesState(stateKey, items[0]?.key);
|
|
21
|
+
const examples = items.find((item) => item.key === state.key)?.examples ?? [];
|
|
22
|
+
if (!items.length && !examples.length) return null;
|
|
23
|
+
return <StaticSection footer={items.length > 1 || examples.length > 1 ? <OpenAPIMediaTypeFooter items={items} examples={examples} selectIcon={selectIcon} stateKey={stateKey} /> : null} className="openapi-response-media-types-examples">
|
|
24
|
+
<OpenAPIMediaTypeBody context={context} stateKey={stateKey} items={items} examples={examples} />
|
|
25
|
+
</StaticSection>;
|
|
26
|
+
}
|
|
27
|
+
function OpenAPIMediaTypeFooter(props) {
|
|
28
|
+
const { items, examples, stateKey, selectIcon } = props;
|
|
29
|
+
return <>
|
|
30
|
+
{items.length > 1 && <OpenAPISelect icon={selectIcon} items={items} stateKey={stateKey} placement="bottom start">
|
|
31
|
+
{items.map((item) => <OpenAPISelectItem key={item.key} id={item.key} value={item}>
|
|
32
|
+
<span>{item.label}</span>
|
|
33
|
+
</OpenAPISelectItem>)}
|
|
34
|
+
</OpenAPISelect>}
|
|
35
|
+
|
|
36
|
+
{examples && examples.length > 1 ? <OpenAPISelect icon={selectIcon} items={examples} stateKey={`${stateKey}-examples`} placement="bottom start">
|
|
37
|
+
{examples.map((example) => <OpenAPISelectItem key={example.key} id={example.key} value={example}>
|
|
38
|
+
<span>{example.label}</span>
|
|
39
|
+
</OpenAPISelectItem>)}
|
|
40
|
+
</OpenAPISelect> : null}
|
|
41
|
+
</>;
|
|
42
|
+
}
|
|
43
|
+
function OpenAPIMediaTypeBody(props) {
|
|
44
|
+
const { stateKey, items, examples, context } = props;
|
|
45
|
+
const state = useMediaTypesState(stateKey, items[0]?.key);
|
|
46
|
+
const selectedItem = items.find((item) => item.key === state.key) ?? items[0];
|
|
47
|
+
const exampleState = useMediaTypeExamplesState(`${stateKey}-examples`, selectedItem?.examples?.[0]?.key);
|
|
48
|
+
if (!selectedItem) return null;
|
|
49
|
+
if (examples) {
|
|
50
|
+
const selectedExample = examples.find((example) => example.key === exampleState.key) ?? examples[0];
|
|
51
|
+
if (!selectedExample) return <OpenAPIEmptyExample context={context} />;
|
|
52
|
+
return selectedExample.body;
|
|
53
|
+
}
|
|
54
|
+
return selectedItem.body;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { OpenAPIMediaTypeContent };
|
|
@@ -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,25 @@
|
|
|
1
|
+
import { getOpenAPIClientContext } from "./context.js";
|
|
2
|
+
import { OpenAPIPathItem } from "./OpenAPIPathItem.js";
|
|
3
|
+
import { formatPath } from "./formatPath.js";
|
|
4
|
+
import { getDefaultServerURL } from "./util/server.js";
|
|
5
|
+
import { OpenAPIPathMultipleServers } from "./OpenAPIPathMultipleServers.js";
|
|
6
|
+
|
|
7
|
+
//#region src/OpenAPIPath.tsx
|
|
8
|
+
/**
|
|
9
|
+
* Display the path of an operation.
|
|
10
|
+
*/
|
|
11
|
+
function OpenAPIPath(props) {
|
|
12
|
+
const { data, withServer = true, context } = props;
|
|
13
|
+
const { path } = data;
|
|
14
|
+
const clientContext = getOpenAPIClientContext(context);
|
|
15
|
+
if (withServer && data.servers.length > 1) return <OpenAPIPathMultipleServers {...props} context={clientContext} />;
|
|
16
|
+
const formattedPath = formatPath(path);
|
|
17
|
+
const defaultServer = getDefaultServerURL(data.servers);
|
|
18
|
+
return <OpenAPIPathItem {...props} value={`${defaultServer}${path}`} context={clientContext}>
|
|
19
|
+
{withServer ? <span className="openapi-path-server">{defaultServer}</span> : null}
|
|
20
|
+
{formattedPath}
|
|
21
|
+
</OpenAPIPathItem>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { OpenAPIPath };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { OpenAPICopyButton } from "./OpenAPICopyButton.js";
|
|
2
|
+
|
|
3
|
+
//#region src/OpenAPIPathItem.tsx
|
|
4
|
+
function OpenAPIPathItem(props) {
|
|
5
|
+
const { value, canCopy = true, context, children, data, copyType = "children" } = props;
|
|
6
|
+
const { operation, method } = data;
|
|
7
|
+
const title = <span className="openapi-path-title">{children}</span>;
|
|
8
|
+
return <div className="openapi-path">
|
|
9
|
+
<div className={`openapi-method openapi-method-${method}`}>{method}</div>
|
|
10
|
+
{canCopy && value ? copyType === "children" ? <OpenAPICopyButton value={value} data-deprecated={operation.deprecated} isDisabled={!canCopy} context={context} className="openapi-path-copy-button">
|
|
11
|
+
{title}
|
|
12
|
+
</OpenAPICopyButton> : <>
|
|
13
|
+
{title}
|
|
14
|
+
<OpenAPICopyButton value={value} data-deprecated={operation.deprecated} isDisabled={!canCopy} context={context} className="openapi-path-copy-button openapi-path-copy-button-icon">
|
|
15
|
+
{context.icons.copy}
|
|
16
|
+
</OpenAPICopyButton>
|
|
17
|
+
</> : title}
|
|
18
|
+
</div>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { OpenAPIPathItem };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { OpenAPITooltip } from "./OpenAPITooltip.js";
|
|
5
|
+
import { createStateKey } from "./utils.js";
|
|
6
|
+
import { OpenAPISelect, OpenAPISelectItem, useSelectState } from "./OpenAPISelect.js";
|
|
7
|
+
import { OpenAPIPathItem } from "./OpenAPIPathItem.js";
|
|
8
|
+
import { formatPath } from "./formatPath.js";
|
|
9
|
+
import { getDefaultServerURL } from "./util/server.js";
|
|
10
|
+
import { Text } from "react-aria-components";
|
|
11
|
+
|
|
12
|
+
//#region src/OpenAPIPathMultipleServers.tsx
|
|
13
|
+
const serversStateKey = createStateKey("servers");
|
|
14
|
+
/**
|
|
15
|
+
* Display the path of an operation.
|
|
16
|
+
*/
|
|
17
|
+
function OpenAPIPathMultipleServers(props) {
|
|
18
|
+
const { data, withServer = true, context } = props;
|
|
19
|
+
const { path, servers } = data;
|
|
20
|
+
const defaultServer = getDefaultServerURL(servers);
|
|
21
|
+
const { key, setKey } = useSelectState(serversStateKey, defaultServer);
|
|
22
|
+
const formattedPath = formatPath(path);
|
|
23
|
+
const items = servers.filter((server) => !!server.url).map((server) => ({
|
|
24
|
+
key: server.url,
|
|
25
|
+
label: server.url,
|
|
26
|
+
description: server.description
|
|
27
|
+
}));
|
|
28
|
+
return <OpenAPIPathItem copyType="button" {...props} value={`${withServer ? key : ""}${path}`} context={context}>
|
|
29
|
+
{withServer ? <OpenAPITooltip>
|
|
30
|
+
<OpenAPISelect className="openapi-select openapi-select-unstyled" items={items} stateKey={serversStateKey} placement="bottom start" icon={context.icons.chevronDown} defaultValue={defaultServer} onChange={setKey}>
|
|
31
|
+
{items.map((item) => <OpenAPISelectItem textValue={item.label} key={item.key} id={item.key} value={item} className="openapi-select-item-column">
|
|
32
|
+
<Text slot="label">{item.label}</Text>
|
|
33
|
+
{item.description ? <Text slot="description">{item.description}</Text> : null}
|
|
34
|
+
</OpenAPISelectItem>)}
|
|
35
|
+
</OpenAPISelect>
|
|
36
|
+
<OpenAPITooltip.Content>Click to select a server</OpenAPITooltip.Content>
|
|
37
|
+
</OpenAPITooltip> : null}
|
|
38
|
+
{formattedPath}
|
|
39
|
+
</OpenAPIPathItem>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { OpenAPIPathMultipleServers };
|
|
@@ -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,67 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { t } from "./translate.js";
|
|
5
|
+
import { OpenAPICopyButton } from "./OpenAPICopyButton.js";
|
|
6
|
+
import { useSelectState } from "./OpenAPISelect.js";
|
|
7
|
+
import { OpenAPIDisclosureGroup } from "./OpenAPIDisclosureGroup.js";
|
|
8
|
+
|
|
9
|
+
//#region src/OpenAPIRequiredScopes.tsx
|
|
10
|
+
/**
|
|
11
|
+
* Present securities authorization that can be used for this operation.
|
|
12
|
+
*/
|
|
13
|
+
function OpenAPIRequiredScopes(props) {
|
|
14
|
+
const { securities, stateKey, context } = props;
|
|
15
|
+
const { key: selectedKey } = useSelectState(stateKey, securities[0]?.key);
|
|
16
|
+
const selectedSecurity = securities.find((security) => security.key === selectedKey);
|
|
17
|
+
if (!selectedSecurity) return null;
|
|
18
|
+
const scopes = selectedSecurity.schemes.flatMap((scheme) => {
|
|
19
|
+
return scheme.scopes ?? [];
|
|
20
|
+
});
|
|
21
|
+
if (!scopes.length) return null;
|
|
22
|
+
return <OpenAPIDisclosureGroup className="openapi-required-scopes" icon={context.icons.chevronRight} stateKey="required-scopes" defaultExpandedKeys={["required-scopes"]} groups={[{
|
|
23
|
+
key: "required-scopes",
|
|
24
|
+
label: <div className="openapi-required-scopes-header">
|
|
25
|
+
{context.icons.lock}
|
|
26
|
+
<span>{t(context.translation, "required_scopes")}</span>
|
|
27
|
+
</div>,
|
|
28
|
+
tabs: [{
|
|
29
|
+
key: "scopes",
|
|
30
|
+
label: "",
|
|
31
|
+
body: <OpenAPISchemaScopes scopes={scopes} context={context} />
|
|
32
|
+
}]
|
|
33
|
+
}]} />;
|
|
34
|
+
}
|
|
35
|
+
function OpenAPISchemaScopes(props) {
|
|
36
|
+
const { scopes, context, isOAuth2 } = props;
|
|
37
|
+
return <div className="openapi-securities-scopes openapi-markdown">
|
|
38
|
+
<div className="openapi-required-scopes-description">
|
|
39
|
+
{t(context.translation, isOAuth2 ? "available_scopes" : "required_scopes_description")}
|
|
40
|
+
</div>
|
|
41
|
+
<ul>
|
|
42
|
+
{scopes.map((scope) => <OpenAPIScopeItem key={scope[0]} scope={scope} context={context} />)}
|
|
43
|
+
</ul>
|
|
44
|
+
</div>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Display a scope item. Either a key-value pair or a single string.
|
|
48
|
+
*/
|
|
49
|
+
function OpenAPIScopeItem(props) {
|
|
50
|
+
const { scope, context } = props;
|
|
51
|
+
return <li>
|
|
52
|
+
<OpenAPIScopeItemKey name={scope[0]} context={context} />
|
|
53
|
+
{scope[1] ? <span>: {scope[1]}</span> : null}
|
|
54
|
+
</li>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Displays the scope name within a copyable button.
|
|
58
|
+
*/
|
|
59
|
+
function OpenAPIScopeItemKey(props) {
|
|
60
|
+
const { name, context } = props;
|
|
61
|
+
return <OpenAPICopyButton value={name} context={context} withTooltip>
|
|
62
|
+
<code>{name}</code>
|
|
63
|
+
</OpenAPICopyButton>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { OpenAPIRequiredScopes, OpenAPISchemaScopes };
|
|
@@ -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 };
|