fumadocs-openapi 10.3.5 → 10.3.7
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 +6 -3
- package/dist/playground/components/oauth-dialog.js +19 -7
- package/dist/playground/components/server-select.js +34 -25
- package/dist/requests/media/encode.js +26 -29
- package/dist/server/create.d.ts +2 -2
- package/dist/types.d.ts +18 -13
- package/dist/ui/api-page.d.ts +3 -4
- package/dist/ui/contexts/api.js +4 -3
- package/dist/ui/operation/index.js +31 -21
- 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 +3 -1
- package/package.json +13 -17
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 };
|
|
@@ -31,7 +31,10 @@ function PlaygroundClient({ route, method = "GET", securities, parameters = [],
|
|
|
31
31
|
const storageKeys = useStorageKey();
|
|
32
32
|
const { mediaAdapters, client: { playground: { components: { ResultDisplay = DefaultResultDisplay } = {}, requestTimeout = 10, transformAuthInputs } = {} } } = useApiContext();
|
|
33
33
|
const { serverRef } = useServerContext();
|
|
34
|
-
const [securityId, setSecurityId] = useState(
|
|
34
|
+
const [securityId, setSecurityId] = useState(() => {
|
|
35
|
+
const idx = securities.findIndex((s) => s.every((entry) => !entry.deprecated));
|
|
36
|
+
return idx === -1 ? 0 : idx;
|
|
37
|
+
});
|
|
35
38
|
const { inputs, mapInputs, initAuthValues } = useAuthInputs(securities[securityId], transformAuthInputs);
|
|
36
39
|
const defaultValues = useMemo(() => {
|
|
37
40
|
const requestData = examples.find((example) => example.id === exampleId)?.data;
|
|
@@ -98,7 +101,7 @@ function PlaygroundClient({ route, method = "GET", securities, parameters = [],
|
|
|
98
101
|
e.preventDefault();
|
|
99
102
|
},
|
|
100
103
|
children: [
|
|
101
|
-
/* @__PURE__ */ jsx(ServerSelect, {}),
|
|
104
|
+
/* @__PURE__ */ jsx(ServerSelect, { className: "border-b" }),
|
|
102
105
|
/* @__PURE__ */ jsxs("div", {
|
|
103
106
|
className: "flex flex-row items-center gap-2 text-sm p-3 not-last:pb-0",
|
|
104
107
|
children: [
|
|
@@ -150,7 +153,7 @@ function SecurityTabs({ securities, setSecurityId, securityId, children }) {
|
|
|
150
153
|
children: security.map((item) => /* @__PURE__ */ jsxs("div", {
|
|
151
154
|
className: "max-w-[600px]",
|
|
152
155
|
children: [/* @__PURE__ */ jsx("p", {
|
|
153
|
-
className: "font-mono font-medium",
|
|
156
|
+
className: cn("font-mono font-medium", item.deprecated && "text-fd-muted-foreground line-through"),
|
|
154
157
|
children: item.id
|
|
155
158
|
}), /* @__PURE__ */ jsx("p", {
|
|
156
159
|
className: "text-fd-muted-foreground whitespace-pre-wrap",
|
|
@@ -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
|
})] })]
|
|
@@ -8,6 +8,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
|
|
@@ -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'>[];
|
|
@@ -41,4 +46,4 @@ interface RenderContext extends Pick<OpenAPIOptions, 'proxyUrl'>, Omit<CreateAPI
|
|
|
41
46
|
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
42
47
|
type Awaitable<T> = T | Promise<T>;
|
|
43
48
|
//#endregion
|
|
44
|
-
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/contexts/api.js
CHANGED
|
@@ -54,6 +54,7 @@ function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
|
54
54
|
const [server, setServer] = useState(() => {
|
|
55
55
|
const defaultItem = defaultBaseUrl ? servers.find((item) => item.url === defaultBaseUrl) : servers[0];
|
|
56
56
|
return defaultItem ? {
|
|
57
|
+
name: defaultItem.name,
|
|
57
58
|
url: defaultItem.url,
|
|
58
59
|
variables: getDefaultValues(defaultItem)
|
|
59
60
|
} : null;
|
|
@@ -64,8 +65,7 @@ function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
|
64
65
|
if (!cached) return;
|
|
65
66
|
try {
|
|
66
67
|
const obj = JSON.parse(cached);
|
|
67
|
-
if (
|
|
68
|
-
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);
|
|
69
69
|
} catch {}
|
|
70
70
|
}, [storageKeys]);
|
|
71
71
|
return /* @__PURE__ */ jsx(ServerSelectContext, {
|
|
@@ -86,6 +86,7 @@ function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
|
86
86
|
const obj = servers.find((item) => item.url === value);
|
|
87
87
|
if (!obj) return;
|
|
88
88
|
const result = {
|
|
89
|
+
name: obj.name,
|
|
89
90
|
url: value,
|
|
90
91
|
variables: getDefaultValues(obj)
|
|
91
92
|
};
|
|
@@ -103,7 +104,7 @@ function ServerSelectProvider({ defaultBaseUrl, children }) {
|
|
|
103
104
|
function getDefaultValues(server) {
|
|
104
105
|
const out = {};
|
|
105
106
|
if (!server.variables) return out;
|
|
106
|
-
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);
|
|
107
108
|
return out;
|
|
108
109
|
}
|
|
109
110
|
|
|
@@ -3,7 +3,7 @@ import { createMethod, methodKeys } from "../../utils/schema.js";
|
|
|
3
3
|
import { isMediaTypeSupported } from "../../requests/media/resolve-adapter.js";
|
|
4
4
|
import "../../requests/media/adapter.js";
|
|
5
5
|
import { cn } from "../../utils/cn.js";
|
|
6
|
-
import { MethodLabel } from "../components/method-label.js";
|
|
6
|
+
import { Badge, MethodLabel } from "../components/method-label.js";
|
|
7
7
|
import { APIPlayground } from "../../playground/index.js";
|
|
8
8
|
import { Schema } from "../schema/index.js";
|
|
9
9
|
import { UsageTabsProviderLazy } from "./usage-tabs/lazy.js";
|
|
@@ -36,7 +36,7 @@ async function Operation({ type = "operation", path, method, ctx, showTitle, sho
|
|
|
36
36
|
headNode = ctx.renderHeading(headingLevel, title);
|
|
37
37
|
headingLevel++;
|
|
38
38
|
}
|
|
39
|
-
const contentTypes = body ? Object.entries(body.content) : null;
|
|
39
|
+
const contentTypes = body?.content ? Object.entries(body.content) : null;
|
|
40
40
|
if (body && contentTypes && contentTypes.length > 0) {
|
|
41
41
|
const items = contentTypes.map(([key]) => ({
|
|
42
42
|
label: /* @__PURE__ */ jsx("code", {
|
|
@@ -100,11 +100,11 @@ async function Operation({ type = "operation", path, method, ctx, showTitle, sho
|
|
|
100
100
|
name: param.name,
|
|
101
101
|
required: param.required
|
|
102
102
|
},
|
|
103
|
-
root: {
|
|
103
|
+
root: typeof param.schema === "object" ? {
|
|
104
104
|
...param.schema,
|
|
105
105
|
description: param.description ?? param.schema?.description,
|
|
106
106
|
deprecated: (param.deprecated ?? false) || (param.schema?.deprecated ?? false)
|
|
107
|
-
},
|
|
107
|
+
} : param.schema,
|
|
108
108
|
readOnly: method.method === "GET",
|
|
109
109
|
writeOnly: method.method !== "GET",
|
|
110
110
|
ctx
|
|
@@ -370,38 +370,48 @@ function WebhookCallback({ callback, ctx, headingLevel }) {
|
|
|
370
370
|
})
|
|
371
371
|
});
|
|
372
372
|
}
|
|
373
|
-
function AuthScheme({ scheme
|
|
374
|
-
if (
|
|
373
|
+
function AuthScheme({ scheme, scopes, ctx }) {
|
|
374
|
+
if (scheme.type === "http" || scheme.type === "oauth2") return /* @__PURE__ */ jsxs(AuthProperty, {
|
|
375
375
|
name: "Authorization",
|
|
376
|
-
type:
|
|
376
|
+
type: scheme.type === "http" && scheme.scheme === "basic" ? `Basic <token>` : "Bearer <token>",
|
|
377
|
+
deprecated: scheme.deprecated,
|
|
377
378
|
scopes,
|
|
378
|
-
children: [
|
|
379
|
+
children: [scheme.description && ctx.renderMarkdown(scheme.description), /* @__PURE__ */ jsxs("p", { children: ["In: ", /* @__PURE__ */ jsx("code", { children: "header" })] })]
|
|
379
380
|
});
|
|
380
|
-
if (
|
|
381
|
-
name:
|
|
381
|
+
if (scheme.type === "apiKey") return /* @__PURE__ */ jsxs(AuthProperty, {
|
|
382
|
+
name: scheme.name,
|
|
382
383
|
type: "<token>",
|
|
384
|
+
deprecated: scheme.deprecated,
|
|
383
385
|
scopes,
|
|
384
|
-
children: [
|
|
386
|
+
children: [scheme.description && ctx.renderMarkdown(scheme.description), /* @__PURE__ */ jsxs("p", { children: ["In: ", /* @__PURE__ */ jsx("code", { children: scheme.in })] })]
|
|
385
387
|
});
|
|
386
|
-
if (
|
|
388
|
+
if (scheme.type === "openIdConnect") return /* @__PURE__ */ jsx(AuthProperty, {
|
|
387
389
|
name: "OpenID Connect",
|
|
388
390
|
type: "<token>",
|
|
391
|
+
deprecated: scheme.deprecated,
|
|
389
392
|
scopes,
|
|
390
|
-
children:
|
|
393
|
+
children: scheme.description && ctx.renderMarkdown(scheme.description)
|
|
391
394
|
});
|
|
392
395
|
}
|
|
393
|
-
function AuthProperty({ name, type, scopes = [], className, ...props }) {
|
|
396
|
+
function AuthProperty({ name, type, deprecated = false, scopes = [], className, ...props }) {
|
|
394
397
|
return /* @__PURE__ */ jsxs("div", {
|
|
395
398
|
className: cn("text-sm border-t my-4 first:border-t-0", className),
|
|
396
399
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
397
400
|
className: "flex flex-wrap items-center gap-3 not-prose",
|
|
398
|
-
children: [
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
401
|
+
children: [
|
|
402
|
+
/* @__PURE__ */ jsx("span", {
|
|
403
|
+
className: "font-medium font-mono text-fd-primary",
|
|
404
|
+
children: name
|
|
405
|
+
}),
|
|
406
|
+
/* @__PURE__ */ jsx("span", {
|
|
407
|
+
className: "text-sm font-mono text-fd-muted-foreground",
|
|
408
|
+
children: type
|
|
409
|
+
}),
|
|
410
|
+
deprecated && /* @__PURE__ */ jsx(Badge, {
|
|
411
|
+
color: "red",
|
|
412
|
+
children: "Deprecated"
|
|
413
|
+
})
|
|
414
|
+
]
|
|
405
415
|
}), /* @__PURE__ */ jsxs("div", {
|
|
406
416
|
className: "prose-no-margin pt-2.5 empty:hidden",
|
|
407
417
|
children: [props.children, scopes.length > 0 && /* @__PURE__ */ jsxs("p", { children: ["Scope: ", /* @__PURE__ */ jsx("code", { children: scopes.join(", ") })] })]
|
|
@@ -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 };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { dereference
|
|
1
|
+
import { dereference } from "@scalar/openapi-parser";
|
|
2
2
|
import { bundle } from "@scalar/json-magic/bundle";
|
|
3
|
+
import { upgrade } from "@scalar/openapi-upgrader";
|
|
3
4
|
import { fetchUrls, readFiles } from "@scalar/json-magic/bundle/plugins/node";
|
|
4
5
|
|
|
5
6
|
//#region src/utils/process-document.ts
|
|
@@ -14,7 +15,7 @@ async function processDocument(input) {
|
|
|
14
15
|
hooks: { onResolveError(node) {
|
|
15
16
|
throw new Error(`Failed to resolve ${node.$ref}`);
|
|
16
17
|
} }
|
|
17
|
-
}).then((v) => upgrade(v
|
|
18
|
+
}).then((v) => upgrade(v, "3.2")).catch((e) => {
|
|
18
19
|
throw new Error(`[OpenAPI] Failed to resolve input: ${input}`, { cause: e });
|
|
19
20
|
});
|
|
20
21
|
/**
|
package/dist/utils/schema.d.ts
CHANGED
package/dist/utils/schema.js
CHANGED
|
@@ -14,7 +14,9 @@ function getPreferredType(body) {
|
|
|
14
14
|
return Object.keys(body)[0];
|
|
15
15
|
}
|
|
16
16
|
function getTagDisplayName(tag) {
|
|
17
|
-
|
|
17
|
+
if ("x-displayName" in tag && typeof tag["x-displayName"] === "string") return tag["x-displayName"];
|
|
18
|
+
if (tag.summary) return tag.summary;
|
|
19
|
+
return idToTitle(tag.name);
|
|
18
20
|
}
|
|
19
21
|
/**
|
|
20
22
|
* Summarize method endpoint information
|