fumadocs-openapi 10.3.4 → 10.3.6
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/css/generated/shared.css +5 -0
- package/dist/_openapi/types.d.ts +880 -0
- package/dist/index.d.ts +2 -2
- package/dist/playground/client.js +4 -3
- package/dist/playground/components/oauth-dialog.js +19 -7
- package/dist/playground/components/server-select.js +36 -27
- package/dist/requests/media/encode.js +26 -29
- package/dist/server/create.d.ts +2 -2
- package/dist/types.d.ts +18 -14
- package/dist/ui/api-page.d.ts +3 -4
- package/dist/ui/api-page.js +7 -3
- package/dist/ui/base.js +0 -3
- package/dist/ui/contexts/api.js +22 -14
- package/dist/ui/contexts/api.lazy.js +2 -1
- package/dist/ui/operation/index.js +11 -5
- package/dist/ui/operation/request-tabs.js +5 -4
- package/dist/utils/pages/preset-auto.js +2 -2
- package/dist/utils/process-document.d.ts +2 -3
- package/dist/utils/process-document.js +3 -2
- package/dist/utils/schema.d.ts +0 -1
- package/dist/utils/schema.js +4 -1
- package/package.json +14 -18
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MediaAdapter } from "./requests/media/adapter.js";
|
|
2
2
|
import { OperationOutput, OutputEntry, OutputGroup, PagesBuilder, PagesBuilderConfig, TagOutput, WebhookOutput, fromSchema, fromServer } from "./utils/pages/builder.js";
|
|
3
3
|
import { SchemaToPagesOptions, createAutoPreset } from "./utils/pages/preset-auto.js";
|
|
4
|
-
import { Awaitable, CallbackObject, DistributiveOmit, Document, MethodInformation, OperationObject, ParameterObject, PathItemObject, ReferenceObject, RenderContext, ResponseObject, SecuritySchemeObject, ServerObject, ServerVariableObject, TagObject } from "./types.js";
|
|
4
|
+
import { Awaitable, CallbackObject, DistributiveOmit, Document, ExampleObject, HttpMethods, MediaTypeObject, MethodInformation, OAuth2SecurityScheme, OperationObject, ParameterObject, PathItemObject, ReferenceObject, RenderContext, RequestBodyObject, ResponseObject, SecuritySchemeObject, ServerObject, ServerVariableObject, TagObject } from "./types.js";
|
|
5
5
|
import { Config, OutputFile, generateFiles, generateFilesOnly } from "./generate-file.js";
|
|
6
|
-
export { Awaitable, CallbackObject, Config, DistributiveOmit, Document, type MediaAdapter, MethodInformation, OperationObject, OperationOutput, OutputEntry, OutputFile, OutputGroup, PagesBuilder, PagesBuilderConfig, ParameterObject, PathItemObject, ReferenceObject, RenderContext, ResponseObject, SchemaToPagesOptions, SecuritySchemeObject, ServerObject, ServerVariableObject, TagObject, TagOutput, WebhookOutput, createAutoPreset, fromSchema, fromServer, generateFiles, generateFilesOnly };
|
|
6
|
+
export { Awaitable, CallbackObject, Config, DistributiveOmit, Document, ExampleObject, HttpMethods, type MediaAdapter, MediaTypeObject, MethodInformation, OAuth2SecurityScheme, OperationObject, OperationOutput, OutputEntry, OutputFile, OutputGroup, PagesBuilder, PagesBuilderConfig, ParameterObject, PathItemObject, ReferenceObject, RenderContext, RequestBodyObject, ResponseObject, SchemaToPagesOptions, SecuritySchemeObject, ServerObject, ServerVariableObject, TagObject, TagOutput, WebhookOutput, createAutoPreset, fromSchema, fromServer, generateFiles, generateFilesOnly };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { joinURL, resolveRequestData, resolveServerUrl, withBase } from "../utils/url.js";
|
|
4
4
|
import { useStorageKey } from "../ui/client/storage-key.js";
|
|
5
|
-
import { useApiContext } from "../ui/contexts/api.js";
|
|
5
|
+
import { useApiContext, useServerContext } from "../ui/contexts/api.js";
|
|
6
6
|
import { getStatusInfo } from "./status-info.js";
|
|
7
7
|
import { cn } from "../utils/cn.js";
|
|
8
8
|
import { MethodLabel } from "../ui/components/method-label.js";
|
|
@@ -29,7 +29,8 @@ const OauthDialogTrigger = lazy(() => import("./components/oauth-dialog.js").the
|
|
|
29
29
|
function PlaygroundClient({ route, method = "GET", securities, parameters = [], body, references, proxyUrl, writeOnly, readOnly, ...rest }) {
|
|
30
30
|
const { example: exampleId, examples, setExampleData } = useExampleRequests();
|
|
31
31
|
const storageKeys = useStorageKey();
|
|
32
|
-
const { mediaAdapters,
|
|
32
|
+
const { mediaAdapters, client: { playground: { components: { ResultDisplay = DefaultResultDisplay } = {}, requestTimeout = 10, transformAuthInputs } = {} } } = useApiContext();
|
|
33
|
+
const { serverRef } = useServerContext();
|
|
33
34
|
const [securityId, setSecurityId] = useState(0);
|
|
34
35
|
const { inputs, mapInputs, initAuthValues } = useAuthInputs(securities[securityId], transformAuthInputs);
|
|
35
36
|
const defaultValues = useMemo(() => {
|
|
@@ -97,7 +98,7 @@ function PlaygroundClient({ route, method = "GET", securities, parameters = [],
|
|
|
97
98
|
e.preventDefault();
|
|
98
99
|
},
|
|
99
100
|
children: [
|
|
100
|
-
/* @__PURE__ */ jsx(ServerSelect, {}),
|
|
101
|
+
/* @__PURE__ */ jsx(ServerSelect, { className: "border-b" }),
|
|
101
102
|
/* @__PURE__ */ jsxs("div", {
|
|
102
103
|
className: "flex flex-row items-center gap-2 text-sm p-3 not-last:pb-0",
|
|
103
104
|
children: [
|
|
@@ -12,25 +12,35 @@ import { useForm } from "react-hook-form";
|
|
|
12
12
|
const FlowTypes = {
|
|
13
13
|
password: {
|
|
14
14
|
name: "Resource Owner Password Flow",
|
|
15
|
-
description: "Authenticate using username and password."
|
|
15
|
+
description: "Authenticate using username and password.",
|
|
16
|
+
supported: true
|
|
16
17
|
},
|
|
17
18
|
clientCredentials: {
|
|
18
19
|
name: "Client Credentials",
|
|
19
|
-
description: "Intended for the server-to-server authentication."
|
|
20
|
+
description: "Intended for the server-to-server authentication.",
|
|
21
|
+
supported: true
|
|
20
22
|
},
|
|
21
23
|
authorizationCode: {
|
|
22
24
|
name: "Authorization code",
|
|
23
|
-
description: "Authenticate with 3rd party services"
|
|
25
|
+
description: "Authenticate with 3rd party services",
|
|
26
|
+
supported: true
|
|
24
27
|
},
|
|
25
28
|
implicit: {
|
|
26
29
|
name: "Implicit",
|
|
27
|
-
description: "Retrieve the access token directly."
|
|
30
|
+
description: "Retrieve the access token directly.",
|
|
31
|
+
supported: true
|
|
32
|
+
},
|
|
33
|
+
deviceAuthorization: {
|
|
34
|
+
name: "Device Authorization",
|
|
35
|
+
description: "Authenticate with device.",
|
|
36
|
+
supported: false
|
|
28
37
|
}
|
|
29
38
|
};
|
|
30
39
|
function OauthDialog({ scheme, scopes, setToken, children, open, setOpen }) {
|
|
31
40
|
const [type, setType] = useState(() => {
|
|
32
41
|
return Object.keys(scheme.flows)[0];
|
|
33
42
|
});
|
|
43
|
+
const { supported } = FlowTypes[type];
|
|
34
44
|
const form = useForm({ defaultValues: {
|
|
35
45
|
clientId: "",
|
|
36
46
|
clientSecret: "",
|
|
@@ -252,15 +262,17 @@ function OauthDialog({ scheme, scopes, setToken, children, open, setOpen }) {
|
|
|
252
262
|
...form.register("password", { required: true })
|
|
253
263
|
})]
|
|
254
264
|
})] }),
|
|
255
|
-
error ? /* @__PURE__ */ jsx("p", {
|
|
265
|
+
supported ? /* @__PURE__ */ jsxs(Fragment$1, { children: [error ? /* @__PURE__ */ jsx("p", {
|
|
256
266
|
className: "text-red-400 font-medium text-sm",
|
|
257
267
|
children: String(error)
|
|
258
|
-
}) : null,
|
|
259
|
-
/* @__PURE__ */ jsx("button", {
|
|
268
|
+
}) : null, /* @__PURE__ */ jsx("button", {
|
|
260
269
|
type: "submit",
|
|
261
270
|
disabled: isLoading,
|
|
262
271
|
className: cn(buttonVariants({ color: "primary" })),
|
|
263
272
|
children: authCodeCallback.isLoading ? "Fetching token..." : "Submit"
|
|
273
|
+
})] }) : /* @__PURE__ */ jsx("p", {
|
|
274
|
+
className: "text-fd-muted-foreground bg-fd-muted p-2 rounded-lg border",
|
|
275
|
+
children: "Unsupported"
|
|
264
276
|
})
|
|
265
277
|
]
|
|
266
278
|
})] })]
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { resolveServerUrl, withBase } from "../../utils/url.js";
|
|
4
|
-
import {
|
|
4
|
+
import { useServerContext, useServerSelectContext } from "../../ui/contexts/api.js";
|
|
5
5
|
import { cn } from "../../utils/cn.js";
|
|
6
6
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/components/select.js";
|
|
7
7
|
import { Input, labelVariants } from "../../ui/components/input.js";
|
|
8
8
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "../../ui/components/dialog.js";
|
|
9
9
|
import { useEffect, useRef, useState } from "react";
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { EditIcon } from "lucide-react";
|
|
11
12
|
import { StfProvider, useFieldValue, useListener, useStf } from "@fumari/stf";
|
|
12
13
|
|
|
13
14
|
//#region src/playground/components/server-select.tsx
|
|
14
15
|
function ServerSelect(props) {
|
|
15
|
-
const { servers } =
|
|
16
|
+
const { servers } = useServerContext();
|
|
16
17
|
const { server, setServer, setServerVariables } = useServerSelectContext();
|
|
17
18
|
const [open, setOpen] = useState(false);
|
|
18
19
|
const [isMounted, setIsMounted] = useState(false);
|
|
@@ -24,34 +25,42 @@ function ServerSelect(props) {
|
|
|
24
25
|
return /* @__PURE__ */ jsxs(Dialog, {
|
|
25
26
|
open,
|
|
26
27
|
onOpenChange: setOpen,
|
|
27
|
-
children: [/* @__PURE__ */
|
|
28
|
-
className: "text-xs p-3 py-2 bg-fd-muted text-fd-muted-foreground transition-colors truncate hover:bg-fd-accent hover:text-fd-accent-foreground focus-visible:outline-none",
|
|
29
|
-
children: isMounted ? withBase(server ? resolveServerUrl(server.url, server.variables) : "/", window.location.origin) : "loading..."
|
|
30
|
-
}), /* @__PURE__ */ jsxs(DialogContent, {
|
|
28
|
+
children: [/* @__PURE__ */ jsxs(DialogTrigger, {
|
|
31
29
|
...props,
|
|
30
|
+
className: cn("flex items-center gap-2 text-sm text-start px-3 py-2 bg-fd-muted text-fd-muted-foreground transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground", props.className),
|
|
32
31
|
children: [
|
|
33
|
-
/* @__PURE__ */
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
onValueChange: setServer,
|
|
37
|
-
children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }), /* @__PURE__ */ jsx(SelectContent, { children: servers.map((item) => /* @__PURE__ */ jsxs(SelectItem, {
|
|
38
|
-
value: item.url,
|
|
39
|
-
children: [/* @__PURE__ */ jsx("code", {
|
|
40
|
-
className: "text-[0.8125rem]",
|
|
41
|
-
children: item.url
|
|
42
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
43
|
-
className: "text-fd-muted-foreground",
|
|
44
|
-
children: item.description
|
|
45
|
-
})]
|
|
46
|
-
}, item.url)) })]
|
|
32
|
+
/* @__PURE__ */ jsx("span", {
|
|
33
|
+
className: "px-2 py-0.5 -ms-2 font-medium rounded-lg border bg-fd-secondary text-fd-secondary-foreground shadow-sm",
|
|
34
|
+
children: server?.name ?? "Server URL"
|
|
47
35
|
}),
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
36
|
+
/* @__PURE__ */ jsx("code", {
|
|
37
|
+
className: "truncate min-w-0 flex-1",
|
|
38
|
+
children: isMounted ? withBase(server ? resolveServerUrl(server.url, server.variables) : "/", window.location.origin) : "loading..."
|
|
39
|
+
}),
|
|
40
|
+
/* @__PURE__ */ jsx(EditIcon, { className: "size-4" })
|
|
53
41
|
]
|
|
54
|
-
})
|
|
42
|
+
}), /* @__PURE__ */ jsxs(DialogContent, { children: [
|
|
43
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Server URL" }), /* @__PURE__ */ jsx(DialogDescription, { children: "The base URL of your API endpoint." })] }),
|
|
44
|
+
/* @__PURE__ */ jsxs(Select, {
|
|
45
|
+
value: server?.url,
|
|
46
|
+
onValueChange: setServer,
|
|
47
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }), /* @__PURE__ */ jsx(SelectContent, { children: servers.map((item) => /* @__PURE__ */ jsxs(SelectItem, {
|
|
48
|
+
value: item.url,
|
|
49
|
+
children: [/* @__PURE__ */ jsx("code", {
|
|
50
|
+
className: "text-[0.8125rem]",
|
|
51
|
+
children: item.url
|
|
52
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
53
|
+
className: "text-fd-muted-foreground",
|
|
54
|
+
children: item.description
|
|
55
|
+
})]
|
|
56
|
+
}, item.url)) })]
|
|
57
|
+
}),
|
|
58
|
+
server?.variables && serverSchema?.variables && /* @__PURE__ */ jsx(ServerSelectContent, {
|
|
59
|
+
defaultValues: server.variables,
|
|
60
|
+
schema: serverSchema.variables,
|
|
61
|
+
onChange: setServerVariables
|
|
62
|
+
}, server.url)
|
|
63
|
+
] })]
|
|
55
64
|
});
|
|
56
65
|
}
|
|
57
66
|
function ServerSelectContent({ defaultValues, onChange, schema }) {
|
|
@@ -102,7 +111,7 @@ function Field({ fieldName, variable }) {
|
|
|
102
111
|
id: fieldName,
|
|
103
112
|
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
104
113
|
}), /* @__PURE__ */ jsx(SelectContent, { children: variable.enum.map((value) => /* @__PURE__ */ jsx(SelectItem, {
|
|
105
|
-
value,
|
|
114
|
+
value: String(value),
|
|
106
115
|
children: value
|
|
107
116
|
}, value)) })]
|
|
108
117
|
});
|
|
@@ -5,7 +5,7 @@ import "./adapter.js";
|
|
|
5
5
|
/**
|
|
6
6
|
* serialize parameters, see https://swagger.io/docs/specification/v3_0/serialization.
|
|
7
7
|
*/
|
|
8
|
-
function encodeRequestData(from, adapters, parameters) {
|
|
8
|
+
function encodeRequestData(from, adapters, parameters = []) {
|
|
9
9
|
const result = {
|
|
10
10
|
method: from.method,
|
|
11
11
|
body: from.body,
|
|
@@ -92,35 +92,32 @@ function serializePathParameter(field, value, output) {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
function serializeQueryParameter(field, value, output) {
|
|
95
|
-
const { explode = true } = field;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
output[field.name] = { values: [Object.entries(value).flat().join(",")] };
|
|
120
|
-
break;
|
|
121
|
-
}
|
|
122
|
-
output[field.name] = { values: [String(value)] };
|
|
95
|
+
const { style, explode = true } = field;
|
|
96
|
+
if (style === "spaceDelimited" && !explode && Array.isArray(value)) {
|
|
97
|
+
output[field.name] = { values: [value.join(" ")] };
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (style === "pipeDelimited" && !explode && Array.isArray(value)) {
|
|
101
|
+
output[field.name] = { values: [value.join("|")] };
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (style === "deepObject" && !Array.isArray(value) && typeof value === "object") {
|
|
105
|
+
for (const [k, v] of Object.entries(value)) output[`${field.name}[${k}]`] = { values: Array.isArray(v) ? v : [String(v)] };
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (Array.isArray(value)) {
|
|
109
|
+
output[field.name] = { values: explode ? value : [value.join(",")] };
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (typeof value === "object" && explode) {
|
|
113
|
+
for (const [k, v] of Object.entries(value)) output[k] = { values: [String(v)] };
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (typeof value === "object") {
|
|
117
|
+
output[field.name] = { values: [Object.entries(value).flat().join(",")] };
|
|
118
|
+
return;
|
|
123
119
|
}
|
|
120
|
+
output[field.name] = { values: [String(value)] };
|
|
124
121
|
}
|
|
125
122
|
function serializeCookieParameter(field, value, output) {
|
|
126
123
|
const { explode = true } = field;
|
package/dist/server/create.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createProxy } from "./proxy.js";
|
|
2
2
|
import { CodeUsageGenerator } from "../ui/operation/usage-tabs/index.js";
|
|
3
|
+
import { Document } from "../types.js";
|
|
3
4
|
import { ProcessedDocument } from "../utils/process-document.js";
|
|
4
|
-
import { OpenAPIV3, OpenAPIV3_1 } from "openapi-types";
|
|
5
5
|
|
|
6
6
|
//#region src/server/create.d.ts
|
|
7
7
|
/**
|
|
8
8
|
* schema id -> file path, URL, or downloaded schema object
|
|
9
9
|
*/
|
|
10
|
-
type SchemaMap = Record<string, string |
|
|
10
|
+
type SchemaMap = Record<string, string | Document>;
|
|
11
11
|
type ProcessedSchemaMap = Record<string, ProcessedDocument>;
|
|
12
12
|
interface OpenAPIOptions {
|
|
13
13
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OpenAPIV3, OpenAPIV3_2 } from "./_openapi/types.js";
|
|
1
2
|
import { NoReference } from "./utils/schema.js";
|
|
2
3
|
import { MediaAdapter } from "./requests/media/adapter.js";
|
|
3
4
|
import { CodeUsageGenerator } from "./ui/operation/usage-tabs/index.js";
|
|
@@ -7,20 +8,24 @@ import { CreateAPIPageOptions } from "./ui/base.js";
|
|
|
7
8
|
import { ProcessedDocument } from "./utils/process-document.js";
|
|
8
9
|
import Slugger from "github-slugger";
|
|
9
10
|
import { HTMLAttributes, ReactNode } from "react";
|
|
10
|
-
import { OpenAPIV3_1 } from "openapi-types";
|
|
11
11
|
|
|
12
12
|
//#region src/types.d.ts
|
|
13
|
-
type Document =
|
|
14
|
-
type OperationObject =
|
|
15
|
-
type ParameterObject =
|
|
16
|
-
type SecuritySchemeObject =
|
|
17
|
-
type ReferenceObject =
|
|
18
|
-
type PathItemObject =
|
|
19
|
-
type TagObject =
|
|
20
|
-
type ServerObject =
|
|
21
|
-
type CallbackObject =
|
|
22
|
-
type ServerVariableObject =
|
|
23
|
-
type ResponseObject =
|
|
13
|
+
type Document = OpenAPIV3_2.Document;
|
|
14
|
+
type OperationObject = OpenAPIV3_2.OperationObject;
|
|
15
|
+
type ParameterObject = OpenAPIV3_2.ParameterObject;
|
|
16
|
+
type SecuritySchemeObject = OpenAPIV3_2.SecuritySchemeObject;
|
|
17
|
+
type ReferenceObject = OpenAPIV3_2.ReferenceObject;
|
|
18
|
+
type PathItemObject = OpenAPIV3_2.PathItemObject;
|
|
19
|
+
type TagObject = OpenAPIV3_2.TagObject;
|
|
20
|
+
type ServerObject = OpenAPIV3_2.ServerObject;
|
|
21
|
+
type CallbackObject = OpenAPIV3_2.CallbackObject;
|
|
22
|
+
type ServerVariableObject = OpenAPIV3.ServerVariableObject;
|
|
23
|
+
type ResponseObject = OpenAPIV3_2.ResponseObject;
|
|
24
|
+
type OAuth2SecurityScheme = OpenAPIV3_2.OAuth2SecurityScheme;
|
|
25
|
+
type HttpMethods = OpenAPIV3_2.HttpMethods;
|
|
26
|
+
type ExampleObject = OpenAPIV3_2.ExampleObject;
|
|
27
|
+
type MediaTypeObject = OpenAPIV3_2.MediaTypeObject;
|
|
28
|
+
type RequestBodyObject = OpenAPIV3_2.RequestBodyObject;
|
|
24
29
|
type MethodInformation = NoReference<OperationObject> & {
|
|
25
30
|
method: string;
|
|
26
31
|
'x-codeSamples'?: Omit<CodeUsageGenerator, 'id'>[];
|
|
@@ -28,7 +33,6 @@ type MethodInformation = NoReference<OperationObject> & {
|
|
|
28
33
|
'x-exclusiveCodeSample'?: string;
|
|
29
34
|
};
|
|
30
35
|
interface RenderContext extends Pick<OpenAPIOptions, 'proxyUrl'>, Omit<CreateAPIPageOptions, 'renderMarkdown'> {
|
|
31
|
-
servers: NoReference<ServerObject>[];
|
|
32
36
|
slugger: Slugger;
|
|
33
37
|
/**
|
|
34
38
|
* dereferenced schema
|
|
@@ -42,4 +46,4 @@ interface RenderContext extends Pick<OpenAPIOptions, 'proxyUrl'>, Omit<CreateAPI
|
|
|
42
46
|
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
43
47
|
type Awaitable<T> = T | Promise<T>;
|
|
44
48
|
//#endregion
|
|
45
|
-
export { Awaitable, CallbackObject, DistributiveOmit, Document, MethodInformation, OperationObject, ParameterObject, PathItemObject, ReferenceObject, RenderContext, ResponseObject, SecuritySchemeObject, ServerObject, ServerVariableObject, TagObject };
|
|
49
|
+
export { Awaitable, CallbackObject, DistributiveOmit, Document, ExampleObject, HttpMethods, MediaTypeObject, MethodInformation, OAuth2SecurityScheme, OperationObject, ParameterObject, PathItemObject, ReferenceObject, RenderContext, RequestBodyObject, ResponseObject, SecuritySchemeObject, ServerObject, ServerVariableObject, TagObject };
|
package/dist/ui/api-page.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import "../types.js";
|
|
1
|
+
import { HttpMethods } from "../types.js";
|
|
2
2
|
import { ProcessedDocument } from "../utils/process-document.js";
|
|
3
3
|
import "react/jsx-runtime";
|
|
4
|
-
import { OpenAPIV3_1 } from "openapi-types";
|
|
5
4
|
|
|
6
5
|
//#region src/ui/api-page.d.ts
|
|
7
6
|
interface ApiPageProps {
|
|
@@ -19,7 +18,7 @@ interface WebhookItem {
|
|
|
19
18
|
* webhook name in `webhooks`
|
|
20
19
|
*/
|
|
21
20
|
name: string;
|
|
22
|
-
method:
|
|
21
|
+
method: HttpMethods;
|
|
23
22
|
}
|
|
24
23
|
interface OperationItem {
|
|
25
24
|
/**
|
|
@@ -29,7 +28,7 @@ interface OperationItem {
|
|
|
29
28
|
/**
|
|
30
29
|
* the HTTP method of operation
|
|
31
30
|
*/
|
|
32
|
-
method:
|
|
31
|
+
method: HttpMethods;
|
|
33
32
|
}
|
|
34
33
|
//#endregion
|
|
35
34
|
export { ApiPageProps, OperationItem, WebhookItem };
|
package/dist/ui/api-page.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createMethod } from "../utils/schema.js";
|
|
2
|
+
import { ApiProviderLazy, ServerProviderLazy } from "./contexts/api.lazy.js";
|
|
2
3
|
import { Operation } from "./operation/index.js";
|
|
3
|
-
import { ApiProviderLazy } from "./contexts/api.lazy.js";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
|
|
6
6
|
//#region src/ui/api-page.tsx
|
|
@@ -46,11 +46,15 @@ async function APIPage({ showTitle: hasHead = false, showDescription, operations
|
|
|
46
46
|
};
|
|
47
47
|
})
|
|
48
48
|
}, ctx);
|
|
49
|
+
let servers = ctx.schema.dereferenced.servers;
|
|
50
|
+
if (!servers || servers.length === 0) servers = [{ url: "/" }];
|
|
49
51
|
return /* @__PURE__ */ jsx(ApiProviderLazy, {
|
|
50
|
-
servers: ctx.servers,
|
|
51
52
|
shikiOptions: ctx.shikiOptions,
|
|
52
53
|
client: ctx.client ?? {},
|
|
53
|
-
children:
|
|
54
|
+
children: /* @__PURE__ */ jsx(ServerProviderLazy, {
|
|
55
|
+
servers,
|
|
56
|
+
children: content
|
|
57
|
+
})
|
|
54
58
|
});
|
|
55
59
|
}
|
|
56
60
|
|
package/dist/ui/base.js
CHANGED
|
@@ -36,14 +36,11 @@ function createAPIPage(server, options) {
|
|
|
36
36
|
let processed;
|
|
37
37
|
if (typeof document === "string") processed = await server.getSchema(document);
|
|
38
38
|
else processed = await document;
|
|
39
|
-
const { dereferenced } = processed;
|
|
40
|
-
const servers = dereferenced.servers && dereferenced.servers.length > 0 ? dereferenced.servers : [{ url: "/" }];
|
|
41
39
|
const slugger = new Slugger();
|
|
42
40
|
const ctx = {
|
|
43
41
|
schema: processed,
|
|
44
42
|
proxyUrl: server.options.proxyUrl,
|
|
45
43
|
...options,
|
|
46
|
-
servers,
|
|
47
44
|
mediaAdapters: {
|
|
48
45
|
...defaultAdapters,
|
|
49
46
|
...options.mediaAdapters
|
package/dist/ui/contexts/api.js
CHANGED
|
@@ -6,6 +6,7 @@ import { createContext, use, useEffect, useMemo, useRef, useState } from "react"
|
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
7
|
|
|
8
8
|
//#region src/ui/contexts/api.tsx
|
|
9
|
+
const ServerContext = createContext(null);
|
|
9
10
|
const ApiContext = createContext(null);
|
|
10
11
|
const ServerSelectContext = createContext(null);
|
|
11
12
|
function useApiContext() {
|
|
@@ -13,28 +14,34 @@ function useApiContext() {
|
|
|
13
14
|
if (!ctx) throw new Error("Component must be used under <ApiProvider />");
|
|
14
15
|
return ctx;
|
|
15
16
|
}
|
|
17
|
+
function useServerContext() {
|
|
18
|
+
return use(ServerContext);
|
|
19
|
+
}
|
|
16
20
|
function useServerSelectContext() {
|
|
17
21
|
const ctx = use(ServerSelectContext);
|
|
18
22
|
if (!ctx) throw new Error("Component must be used under <ApiProvider />");
|
|
19
23
|
return ctx;
|
|
20
24
|
}
|
|
21
|
-
function ApiProvider({
|
|
22
|
-
const serverRef = useRef(null);
|
|
25
|
+
function ApiProvider({ children, shikiOptions, client }) {
|
|
23
26
|
return /* @__PURE__ */ jsx(ApiContext, {
|
|
24
27
|
value: useMemo(() => ({
|
|
25
|
-
serverRef,
|
|
26
28
|
shikiOptions,
|
|
27
29
|
client,
|
|
28
30
|
mediaAdapters: {
|
|
29
31
|
...defaultAdapters,
|
|
30
32
|
...client.mediaAdapters
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
}
|
|
34
|
+
}), [client, shikiOptions]),
|
|
35
|
+
children
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function ServerProvider({ servers, defaultBaseUrl, children }) {
|
|
39
|
+
const serverRef = useRef(null);
|
|
40
|
+
return /* @__PURE__ */ jsx(ServerContext, {
|
|
41
|
+
value: useMemo(() => ({
|
|
34
42
|
servers,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
]),
|
|
43
|
+
serverRef
|
|
44
|
+
}), [servers]),
|
|
38
45
|
children: /* @__PURE__ */ jsx(ServerSelectProvider, {
|
|
39
46
|
defaultBaseUrl,
|
|
40
47
|
children
|
|
@@ -42,11 +49,12 @@ function ApiProvider({ defaultBaseUrl, children, servers, shikiOptions, client }
|
|
|
42
49
|
});
|
|
43
50
|
}
|
|
44
51
|
function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
45
|
-
const { servers, serverRef } =
|
|
52
|
+
const { servers, serverRef } = use(ServerContext);
|
|
46
53
|
const storageKeys = useStorageKey();
|
|
47
54
|
const [server, setServer] = useState(() => {
|
|
48
55
|
const defaultItem = defaultBaseUrl ? servers.find((item) => item.url === defaultBaseUrl) : servers[0];
|
|
49
56
|
return defaultItem ? {
|
|
57
|
+
name: defaultItem.name,
|
|
50
58
|
url: defaultItem.url,
|
|
51
59
|
variables: getDefaultValues(defaultItem)
|
|
52
60
|
} : null;
|
|
@@ -57,8 +65,7 @@ function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
|
57
65
|
if (!cached) return;
|
|
58
66
|
try {
|
|
59
67
|
const obj = JSON.parse(cached);
|
|
60
|
-
if (
|
|
61
|
-
setServer(obj);
|
|
68
|
+
if (typeof obj === "object" && obj !== null && "url" in obj && typeof obj.url === "string" && "variables" in obj && typeof obj.variables === "object" && obj.variables !== null) setServer(obj);
|
|
62
69
|
} catch {}
|
|
63
70
|
}, [storageKeys]);
|
|
64
71
|
return /* @__PURE__ */ jsx(ServerSelectContext, {
|
|
@@ -79,6 +86,7 @@ function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
|
79
86
|
const obj = servers.find((item) => item.url === value);
|
|
80
87
|
if (!obj) return;
|
|
81
88
|
const result = {
|
|
89
|
+
name: obj.name,
|
|
82
90
|
url: value,
|
|
83
91
|
variables: getDefaultValues(obj)
|
|
84
92
|
};
|
|
@@ -96,9 +104,9 @@ function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
|
96
104
|
function getDefaultValues(server) {
|
|
97
105
|
const out = {};
|
|
98
106
|
if (!server.variables) return out;
|
|
99
|
-
for (const [k, v] of Object.entries(server.variables)) out[k] = v.default;
|
|
107
|
+
for (const [k, v] of Object.entries(server.variables)) if (v.default !== void 0) out[k] = String(v.default);
|
|
100
108
|
return out;
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
//#endregion
|
|
104
|
-
export { ApiProvider, useApiContext, useServerSelectContext };
|
|
112
|
+
export { ApiProvider, ServerProvider, useApiContext, useServerContext, useServerSelectContext };
|
|
@@ -4,6 +4,7 @@ import { wrapLazy } from "../../utils/lazy.js";
|
|
|
4
4
|
|
|
5
5
|
//#region src/ui/contexts/api.lazy.ts
|
|
6
6
|
const ApiProviderLazy = wrapLazy(() => import("./api.js").then((mod) => ({ default: mod.ApiProvider })));
|
|
7
|
+
const ServerProviderLazy = wrapLazy(() => import("./api.js").then((mod) => ({ default: mod.ServerProvider })));
|
|
7
8
|
|
|
8
9
|
//#endregion
|
|
9
|
-
export { ApiProviderLazy };
|
|
10
|
+
export { ApiProviderLazy, ServerProviderLazy };
|
|
@@ -11,6 +11,7 @@ import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Acc
|
|
|
11
11
|
import { UsageTabs } from "./usage-tabs/index.js";
|
|
12
12
|
import { CopyResponseTypeScript, SelectTab, SelectTabTrigger, SelectTabs } from "./client.js";
|
|
13
13
|
import { RequestTabs, getExampleRequests } from "./request-tabs.js";
|
|
14
|
+
import { ServerProviderLazy } from "../contexts/api.lazy.js";
|
|
14
15
|
import { Fragment } from "react";
|
|
15
16
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
16
17
|
|
|
@@ -35,7 +36,7 @@ async function Operation({ type = "operation", path, method, ctx, showTitle, sho
|
|
|
35
36
|
headNode = ctx.renderHeading(headingLevel, title);
|
|
36
37
|
headingLevel++;
|
|
37
38
|
}
|
|
38
|
-
const contentTypes = body ? Object.entries(body.content) : null;
|
|
39
|
+
const contentTypes = body?.content ? Object.entries(body.content) : null;
|
|
39
40
|
if (body && contentTypes && contentTypes.length > 0) {
|
|
40
41
|
const items = contentTypes.map(([key]) => ({
|
|
41
42
|
label: /* @__PURE__ */ jsx("code", {
|
|
@@ -99,11 +100,11 @@ async function Operation({ type = "operation", path, method, ctx, showTitle, sho
|
|
|
99
100
|
name: param.name,
|
|
100
101
|
required: param.required
|
|
101
102
|
},
|
|
102
|
-
root: {
|
|
103
|
+
root: typeof param.schema === "object" ? {
|
|
103
104
|
...param.schema,
|
|
104
105
|
description: param.description ?? param.schema?.description,
|
|
105
106
|
deprecated: (param.deprecated ?? false) || (param.schema?.deprecated ?? false)
|
|
106
|
-
},
|
|
107
|
+
} : param.schema,
|
|
107
108
|
readOnly: method.method === "GET",
|
|
108
109
|
writeOnly: method.method !== "GET",
|
|
109
110
|
ctx
|
|
@@ -211,7 +212,7 @@ async function Operation({ type = "operation", path, method, ctx, showTitle, sho
|
|
|
211
212
|
});
|
|
212
213
|
};
|
|
213
214
|
const playgroundEnabled = ctx.playground?.enabled ?? true;
|
|
214
|
-
|
|
215
|
+
let content = await renderOperationLayout({
|
|
215
216
|
header: headNode,
|
|
216
217
|
description: descriptionNode,
|
|
217
218
|
authSchemes: authNode,
|
|
@@ -238,12 +239,17 @@ async function Operation({ type = "operation", path, method, ctx, showTitle, sho
|
|
|
238
239
|
ctx
|
|
239
240
|
})
|
|
240
241
|
}, ctx, method);
|
|
241
|
-
|
|
242
|
+
content = /* @__PURE__ */ jsx(UsageTabsProviderLazy, {
|
|
242
243
|
defaultExampleId: method["x-exclusiveCodeSample"] ?? method["x-selectedCodeSample"],
|
|
243
244
|
route: path,
|
|
244
245
|
examples: getExampleRequests(path, method, ctx),
|
|
245
246
|
children: content
|
|
246
247
|
});
|
|
248
|
+
if (method.servers) content = /* @__PURE__ */ jsx(ServerProviderLazy, {
|
|
249
|
+
servers: method.servers,
|
|
250
|
+
children: content
|
|
251
|
+
});
|
|
252
|
+
return content;
|
|
247
253
|
} else {
|
|
248
254
|
renderWebhookLayout ??= (slots) => /* @__PURE__ */ jsxs("div", {
|
|
249
255
|
className: "flex flex-col-reverse gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
|
|
@@ -9,8 +9,9 @@ import { sample } from "openapi-sampler";
|
|
|
9
9
|
|
|
10
10
|
//#region src/ui/operation/request-tabs.tsx
|
|
11
11
|
function getExampleRequests(path, operation, ctx) {
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
const requestBody = operation.requestBody;
|
|
13
|
+
const media = requestBody?.content ? getPreferredType(requestBody.content) : null;
|
|
14
|
+
const bodyOfType = media ? requestBody.content[media] : null;
|
|
14
15
|
if (bodyOfType?.examples) {
|
|
15
16
|
const result = [];
|
|
16
17
|
for (const [key, value] of Object.entries(bodyOfType.examples)) {
|
|
@@ -29,7 +30,7 @@ function getExampleRequests(path, operation, ctx) {
|
|
|
29
30
|
return [{
|
|
30
31
|
id: "_default",
|
|
31
32
|
name: "Default",
|
|
32
|
-
description: bodyOfType?.schema
|
|
33
|
+
description: typeof bodyOfType?.schema === "object" ? bodyOfType.schema.description : void 0,
|
|
33
34
|
data,
|
|
34
35
|
encoded: encodeRequestData(data, ctx.mediaAdapters, operation.parameters ?? [])
|
|
35
36
|
}];
|
|
@@ -66,7 +67,7 @@ function getRequestData(path, method, sampleKey, _ctx) {
|
|
|
66
67
|
default: result.path[param.name] = value;
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
|
-
if (method.requestBody) {
|
|
70
|
+
if (method.requestBody?.content) {
|
|
70
71
|
const body = method.requestBody.content;
|
|
71
72
|
const type = getPreferredType(body);
|
|
72
73
|
if (!type) throw new Error(`Cannot find body schema for ${path} ${method.method}: missing media type`);
|
|
@@ -52,8 +52,8 @@ function createAutoPreset(options) {
|
|
|
52
52
|
schemaId: builder.id,
|
|
53
53
|
path: "",
|
|
54
54
|
info: {
|
|
55
|
-
title: dereferenced.info
|
|
56
|
-
description: dereferenced.info
|
|
55
|
+
title: dereferenced.info?.title ?? "Unknown",
|
|
56
|
+
description: dereferenced.info?.description
|
|
57
57
|
},
|
|
58
58
|
...items
|
|
59
59
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { NoReference } from "./schema.js";
|
|
2
2
|
import { Document } from "../types.js";
|
|
3
|
-
import { OpenAPIV3, OpenAPIV3_1 } from "openapi-types";
|
|
4
3
|
|
|
5
4
|
//#region src/utils/process-document.d.ts
|
|
6
|
-
|
|
5
|
+
interface ProcessedDocument {
|
|
7
6
|
/**
|
|
8
7
|
* dereferenced document
|
|
9
8
|
*/
|
|
@@ -14,6 +13,6 @@ type ProcessedDocument = {
|
|
|
14
13
|
*/
|
|
15
14
|
getRawRef: (obj: object) => string | undefined;
|
|
16
15
|
bundled: Document;
|
|
17
|
-
}
|
|
16
|
+
}
|
|
18
17
|
//#endregion
|
|
19
18
|
export { ProcessedDocument };
|