fumadocs-openapi 10.6.6 → 10.6.8
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 +29 -5
- package/dist/_virtual/_rolldown/runtime.js +2 -1
- package/dist/i18n.d.ts +2 -1
- package/dist/i18n.js +5 -3
- package/dist/node_modules/.pnpm/@fastify_deepmerge@3.2.1/node_modules/@fastify/deepmerge/index.js +108 -0
- package/dist/node_modules/.pnpm/fast-content-type-parse@3.0.0/node_modules/fast-content-type-parse/index.js +115 -0
- package/dist/playground/client.d.ts +3 -11
- package/dist/playground/client.js +3 -37
- package/dist/playground/components/inputs.js +2 -2
- package/dist/playground/components/oauth-dialog.js +18 -12
- package/dist/playground/components/result-display.d.ts +16 -0
- package/dist/playground/components/result-display.js +142 -0
- package/dist/playground/components/server-select.js +1 -1
- package/dist/playground/fetcher.d.ts +9 -3
- package/dist/playground/fetcher.js +7 -18
- package/dist/playground/schema.js +1 -1
- package/dist/playground/status-info.js +27 -23
- package/dist/scalar/client.js +14 -23
- package/dist/ui/base.js +1 -1
- package/dist/ui/client/i18n.js +6 -4
- package/dist/ui/components/dialog.js +1 -1
- package/dist/ui/operation/client.js +1 -1
- package/dist/ui/operation/get-example-requests.js +1 -1
- package/dist/ui/operation/index.js +1 -1
- package/dist/ui/operation/request-tabs.js +1 -1
- package/dist/ui/operation/response-tabs.js +1 -1
- package/dist/ui/operation/usage-tabs/client.js +1 -1
- package/dist/ui/schema/client.js +2 -2
- package/dist/ui/schema/index.js +1 -1
- package/dist/utils/schema/sample.js +442 -0
- package/package.json +18 -16
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { useApiContext } from "../../ui/contexts/api.js";
|
|
2
|
+
import { useTranslations } from "../../ui/client/i18n.js";
|
|
2
3
|
import { cn } from "../../utils/cn.js";
|
|
3
4
|
import { useQuery } from "../../utils/use-query.js";
|
|
4
5
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/components/select.js";
|
|
5
6
|
import { Input, labelVariants } from "../../ui/components/input.js";
|
|
6
|
-
import { useTranslations } from "../../ui/client/i18n.js";
|
|
7
7
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "../../ui/components/dialog.js";
|
|
8
8
|
import { useAuth } from "../auth.js";
|
|
9
9
|
import { useMemo, useState } from "react";
|
|
10
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
12
|
-
import { useForm } from "react-hook-form";
|
|
13
12
|
//#region src/playground/components/oauth-dialog.tsx
|
|
14
13
|
const OAuthDialog = Dialog;
|
|
15
14
|
function OAuthDialogContent(props) {
|
|
@@ -52,14 +51,14 @@ function Content({ schemeId, scopes, setToken, setOpen }) {
|
|
|
52
51
|
supported: false
|
|
53
52
|
}
|
|
54
53
|
}), [t]);
|
|
55
|
-
const
|
|
54
|
+
const defaultValues = useMemo(() => {
|
|
56
55
|
return {
|
|
57
56
|
clientId: tokenInfo?.client_id ?? "",
|
|
58
57
|
clientSecret: tokenInfo?.type === "authorization_code" ? tokenInfo.client_secret : "",
|
|
59
58
|
username: "",
|
|
60
59
|
password: ""
|
|
61
60
|
};
|
|
62
|
-
}, [tokenInfo])
|
|
61
|
+
}, [tokenInfo]);
|
|
63
62
|
const authorize = useQuery(async (values) => {
|
|
64
63
|
if (type === "implicit") {
|
|
65
64
|
const value = scheme.flows[type];
|
|
@@ -127,13 +126,12 @@ function Content({ schemeId, scopes, setToken, setOpen }) {
|
|
|
127
126
|
}
|
|
128
127
|
});
|
|
129
128
|
const isLoading = authorize.isLoading;
|
|
130
|
-
const onSubmit = form.handleSubmit((values) => {
|
|
131
|
-
return authorize.start(values);
|
|
132
|
-
});
|
|
133
129
|
return /* @__PURE__ */ jsxs("form", {
|
|
134
130
|
className: "flex flex-col gap-6",
|
|
135
131
|
onSubmit: (e) => {
|
|
136
|
-
|
|
132
|
+
const formData = new FormData(e.target);
|
|
133
|
+
authorize.start(Object.fromEntries(formData.entries()));
|
|
134
|
+
e.preventDefault();
|
|
137
135
|
e.stopPropagation();
|
|
138
136
|
},
|
|
139
137
|
children: [
|
|
@@ -168,11 +166,13 @@ function Content({ schemeId, scopes, setToken, setOpen }) {
|
|
|
168
166
|
}),
|
|
169
167
|
/* @__PURE__ */ jsx(Input, {
|
|
170
168
|
id: "client_id",
|
|
169
|
+
name: "clientId",
|
|
171
170
|
placeholder: t.inputPlaceholder,
|
|
172
171
|
type: "text",
|
|
173
172
|
autoComplete: "off",
|
|
174
173
|
disabled: isLoading,
|
|
175
|
-
|
|
174
|
+
defaultValue: defaultValues.clientId,
|
|
175
|
+
required: true
|
|
176
176
|
})
|
|
177
177
|
]
|
|
178
178
|
}),
|
|
@@ -190,11 +190,13 @@ function Content({ schemeId, scopes, setToken, setOpen }) {
|
|
|
190
190
|
}),
|
|
191
191
|
/* @__PURE__ */ jsx(Input, {
|
|
192
192
|
id: "client_secret",
|
|
193
|
+
name: "clientSecret",
|
|
193
194
|
placeholder: t.inputPlaceholder,
|
|
194
195
|
type: "password",
|
|
195
196
|
autoComplete: "off",
|
|
196
197
|
disabled: isLoading,
|
|
197
|
-
|
|
198
|
+
defaultValue: defaultValues.clientSecret,
|
|
199
|
+
required: true
|
|
198
200
|
})
|
|
199
201
|
]
|
|
200
202
|
}),
|
|
@@ -206,11 +208,13 @@ function Content({ schemeId, scopes, setToken, setOpen }) {
|
|
|
206
208
|
children: t.usernameField
|
|
207
209
|
}), /* @__PURE__ */ jsx(Input, {
|
|
208
210
|
id: "username",
|
|
211
|
+
name: "username",
|
|
209
212
|
placeholder: t.inputPlaceholder,
|
|
210
213
|
type: "text",
|
|
211
214
|
autoComplete: "off",
|
|
212
215
|
disabled: isLoading,
|
|
213
|
-
|
|
216
|
+
defaultValue: defaultValues.username,
|
|
217
|
+
required: true
|
|
214
218
|
})]
|
|
215
219
|
}), /* @__PURE__ */ jsxs("fieldset", {
|
|
216
220
|
className: "flex flex-col gap-1.5",
|
|
@@ -220,11 +224,13 @@ function Content({ schemeId, scopes, setToken, setOpen }) {
|
|
|
220
224
|
children: t.clientSecret
|
|
221
225
|
}), /* @__PURE__ */ jsx(Input, {
|
|
222
226
|
id: "password",
|
|
227
|
+
name: "password",
|
|
223
228
|
placeholder: t.inputPlaceholder,
|
|
224
229
|
type: "password",
|
|
225
230
|
autoComplete: "off",
|
|
226
231
|
disabled: isLoading,
|
|
227
|
-
|
|
232
|
+
defaultValue: defaultValues.password,
|
|
233
|
+
required: true
|
|
228
234
|
})]
|
|
229
235
|
})] }),
|
|
230
236
|
type && allFlows[type].supported ? /* @__PURE__ */ jsxs(Fragment$1, { children: [authorize.error ? /* @__PURE__ */ jsx("p", {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FetchResult } from "../fetcher.js";
|
|
2
|
+
import { ComponentProps } from "react";
|
|
3
|
+
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/playground/components/result-display.d.ts
|
|
6
|
+
interface ResultDisplayProps extends ComponentProps<'div'> {
|
|
7
|
+
data: FetchResult;
|
|
8
|
+
reset: () => void;
|
|
9
|
+
}
|
|
10
|
+
declare function DefaultResultDisplay({
|
|
11
|
+
data,
|
|
12
|
+
reset,
|
|
13
|
+
...rest
|
|
14
|
+
}: ResultDisplayProps): _$react_jsx_runtime0.JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { DefaultResultDisplay, ResultDisplayProps };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useTranslations, withReplacements } from "../../ui/client/i18n.js";
|
|
3
|
+
import { useStatusInfo } from "../status-info.js";
|
|
4
|
+
import { cn } from "../../utils/cn.js";
|
|
5
|
+
import { ClientCodeBlock } from "../../ui/components/codeblock.js";
|
|
6
|
+
import { require_fast_content_type_parse } from "../../node_modules/.pnpm/fast-content-type-parse@3.0.0/node_modules/fast-content-type-parse/index.js";
|
|
7
|
+
import { useEffect, useMemo, useState } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { CircleX } from "lucide-react";
|
|
10
|
+
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
11
|
+
import { cva } from "class-variance-authority";
|
|
12
|
+
//#region src/playground/components/result-display.tsx
|
|
13
|
+
var import_fast_content_type_parse = require_fast_content_type_parse();
|
|
14
|
+
const panelVariants = cva("flex flex-col gap-2 mt-2 px-3 py-2 border-y bg-fd-secondary text-fd-secondary-foreground");
|
|
15
|
+
function DefaultResultDisplay({ data, reset, ...rest }) {
|
|
16
|
+
const t = useTranslations();
|
|
17
|
+
if (data.type === "client_error") return /* @__PURE__ */ jsxs("div", {
|
|
18
|
+
...rest,
|
|
19
|
+
className: cn(panelVariants(), rest.className),
|
|
20
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
21
|
+
className: "flex gap-1.5 items-center",
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ jsx(CircleX, { className: "size-4 text-red-500" }),
|
|
24
|
+
/* @__PURE__ */ jsx("p", {
|
|
25
|
+
className: "text-sm font-medium me-auto",
|
|
26
|
+
children: t.statusClientError
|
|
27
|
+
}),
|
|
28
|
+
/* @__PURE__ */ jsx("button", {
|
|
29
|
+
type: "button",
|
|
30
|
+
className: cn(buttonVariants({
|
|
31
|
+
size: "sm",
|
|
32
|
+
variant: "outline"
|
|
33
|
+
})),
|
|
34
|
+
onClick: () => reset(),
|
|
35
|
+
children: t.close
|
|
36
|
+
})
|
|
37
|
+
]
|
|
38
|
+
}), /* @__PURE__ */ jsx("p", { children: data.message })]
|
|
39
|
+
});
|
|
40
|
+
return /* @__PURE__ */ jsx(ResponseResult, {
|
|
41
|
+
data,
|
|
42
|
+
reset,
|
|
43
|
+
...rest
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function getTextFormat(mime) {
|
|
47
|
+
switch (mime) {
|
|
48
|
+
case "application/json": return "json";
|
|
49
|
+
case "text/html": return "html";
|
|
50
|
+
case "text/css": return "css";
|
|
51
|
+
case "text/csv": return "csv";
|
|
52
|
+
case "application/javascript":
|
|
53
|
+
case "application/x-javascript": return "js";
|
|
54
|
+
case "application/xml": return "xml";
|
|
55
|
+
}
|
|
56
|
+
if (mime.endsWith("+json")) return "json";
|
|
57
|
+
if (mime.endsWith("+xml")) return "xml";
|
|
58
|
+
if (mime.startsWith("text/")) return "text";
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
function ResponseResult({ data, reset, ...rest }) {
|
|
62
|
+
const t = useTranslations();
|
|
63
|
+
const statusInfo = useStatusInfo(data.status);
|
|
64
|
+
const { parameters, type } = useMemo(() => (0, import_fast_content_type_parse.safeParse)(data.headers.get("Content-Type") ?? "text/plain"), [data.headers]);
|
|
65
|
+
let content;
|
|
66
|
+
if (type.startsWith("image/")) content = /* @__PURE__ */ jsx(ImageResult, {
|
|
67
|
+
mime: type,
|
|
68
|
+
buffer: data.body
|
|
69
|
+
});
|
|
70
|
+
else if (data.body.byteLength > 0) {
|
|
71
|
+
const lang = getTextFormat(type);
|
|
72
|
+
if (lang) content = /* @__PURE__ */ jsx(TextResult, {
|
|
73
|
+
lang,
|
|
74
|
+
charset: parameters.charset,
|
|
75
|
+
data
|
|
76
|
+
});
|
|
77
|
+
else content = /* @__PURE__ */ jsx("p", {
|
|
78
|
+
className: "p-2 border rounded-lg bg-fd-card text-fd-card-foreground",
|
|
79
|
+
children: withReplacements(t.statusBinaryBody, { length: String(data.body.byteLength) })
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
83
|
+
...rest,
|
|
84
|
+
className: cn(panelVariants(), rest.className),
|
|
85
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
86
|
+
className: "flex items-center gap-1.5",
|
|
87
|
+
children: [
|
|
88
|
+
/* @__PURE__ */ jsx(statusInfo.icon, { className: cn("size-4 shrink-0", statusInfo.color) }),
|
|
89
|
+
/* @__PURE__ */ jsxs("p", {
|
|
90
|
+
className: "text-sm font-medium text-nowrap",
|
|
91
|
+
children: [
|
|
92
|
+
data.status,
|
|
93
|
+
" ",
|
|
94
|
+
statusInfo.description
|
|
95
|
+
]
|
|
96
|
+
}),
|
|
97
|
+
/* @__PURE__ */ jsx("code", {
|
|
98
|
+
className: "ms-auto text-xs text-fd-muted-foreground truncate",
|
|
99
|
+
children: type
|
|
100
|
+
}),
|
|
101
|
+
/* @__PURE__ */ jsx("button", {
|
|
102
|
+
type: "button",
|
|
103
|
+
className: cn(buttonVariants({
|
|
104
|
+
size: "sm",
|
|
105
|
+
variant: "outline"
|
|
106
|
+
})),
|
|
107
|
+
onClick: () => reset(),
|
|
108
|
+
children: t.close
|
|
109
|
+
})
|
|
110
|
+
]
|
|
111
|
+
}), content]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function TextResult({ lang, charset, data }) {
|
|
115
|
+
const code = useMemo(() => {
|
|
116
|
+
if (charset) try {
|
|
117
|
+
return new TextDecoder(charset).decode(data.body);
|
|
118
|
+
} catch {}
|
|
119
|
+
return new TextDecoder("utf-8").decode(data.body);
|
|
120
|
+
}, [charset, data.body]);
|
|
121
|
+
return /* @__PURE__ */ jsx(ClientCodeBlock, {
|
|
122
|
+
lang: code.length > 5e3 ? "text" : lang,
|
|
123
|
+
code
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
function ImageResult({ mime, buffer }) {
|
|
127
|
+
const [objectUrl, setObjectUrl] = useState(null);
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
const blob = new Blob([buffer], { type: mime });
|
|
130
|
+
const url = URL.createObjectURL(blob);
|
|
131
|
+
setObjectUrl(url);
|
|
132
|
+
return () => URL.revokeObjectURL(url);
|
|
133
|
+
}, [mime, buffer]);
|
|
134
|
+
if (!objectUrl) return;
|
|
135
|
+
return /* @__PURE__ */ jsx("img", {
|
|
136
|
+
src: objectUrl,
|
|
137
|
+
alt: "",
|
|
138
|
+
className: "w-full rounded-md border border-fd-border"
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
export { DefaultResultDisplay };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { resolveServerUrl, withBase } from "../../utils/url.js";
|
|
3
3
|
import { useServerContext } from "../../ui/contexts/api.js";
|
|
4
|
+
import { useTranslations } from "../../ui/client/i18n.js";
|
|
4
5
|
import { cn } from "../../utils/cn.js";
|
|
5
6
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/components/select.js";
|
|
6
7
|
import { Input, labelVariants } from "../../ui/components/input.js";
|
|
7
|
-
import { useTranslations } from "../../ui/client/i18n.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";
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { Awaitable } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/playground/fetcher.d.ts
|
|
4
|
-
|
|
4
|
+
type FetchResult = FetchResponseResult | FetchErrorResult;
|
|
5
|
+
interface FetchErrorResult {
|
|
6
|
+
type: 'client_error';
|
|
7
|
+
message: string;
|
|
8
|
+
}
|
|
9
|
+
interface FetchResponseResult {
|
|
10
|
+
type: 'response';
|
|
5
11
|
status: number;
|
|
6
|
-
|
|
7
|
-
|
|
12
|
+
headers: Headers;
|
|
13
|
+
body: ArrayBuffer;
|
|
8
14
|
}
|
|
9
15
|
interface BrowserFetcherOptions {
|
|
10
16
|
/**
|
|
@@ -21,9 +21,8 @@ function createBrowserFetcher(adapters, { proxyUrl, proxyForwardCookie = true, r
|
|
|
21
21
|
if (data.bodyMediaType && data.body) {
|
|
22
22
|
const adapter = resolveMediaAdapter(data.bodyMediaType, adapters);
|
|
23
23
|
if (!adapter) return {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
data: `[Fumadocs] No adapter for ${data.bodyMediaType}, you need to specify one from 'createOpenAPI()'.`
|
|
24
|
+
type: "client_error",
|
|
25
|
+
message: `[Fumadocs] No adapter for ${data.bodyMediaType}, you need to specify one from 'createOpenAPI()'.`
|
|
27
26
|
};
|
|
28
27
|
if (data.bodyMediaType !== "multipart/form-data") headers.append("Content-Type", data.bodyMediaType);
|
|
29
28
|
requestInit.body = adapter.encode(data);
|
|
@@ -41,26 +40,16 @@ function createBrowserFetcher(adapters, { proxyUrl, proxyForwardCookie = true, r
|
|
|
41
40
|
}
|
|
42
41
|
if (onRequestInit) requestInit = await onRequestInit(requestInit);
|
|
43
42
|
return fetch(requestUrl, requestInit).then(async (res) => {
|
|
44
|
-
const contentType = res.headers.get("Content-Type") ?? "";
|
|
45
|
-
let type;
|
|
46
|
-
let data;
|
|
47
|
-
if (contentType.startsWith("application/json")) {
|
|
48
|
-
type = "json";
|
|
49
|
-
data = await res.json();
|
|
50
|
-
} else {
|
|
51
|
-
type = contentType.startsWith("text/html") ? "html" : "text";
|
|
52
|
-
data = await res.text();
|
|
53
|
-
}
|
|
54
43
|
return {
|
|
44
|
+
type: "response",
|
|
55
45
|
status: res.status,
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
headers: res.headers,
|
|
47
|
+
body: await res.arrayBuffer()
|
|
58
48
|
};
|
|
59
49
|
}).catch((e) => {
|
|
60
50
|
return {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
data: `Client side error: ${e instanceof Error ? `[${e.name}] ${e.message}` : e.toString()}`
|
|
51
|
+
type: "client_error",
|
|
52
|
+
message: `Client side error: ${e instanceof Error ? `[${e.name}] ${e.message}` : e.toString()}`
|
|
64
53
|
};
|
|
65
54
|
});
|
|
66
55
|
} };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mergeAllOf } from "../utils/schema/merge.js";
|
|
2
|
+
import { sample } from "../utils/schema/sample.js";
|
|
2
3
|
import { schemaToString } from "../utils/schema/to-string.js";
|
|
3
4
|
import { dereferenceSwallow } from "../utils/schema/dereference.js";
|
|
4
5
|
import { createContext, use, useMemo } from "react";
|
|
@@ -6,7 +7,6 @@ import { jsx } from "react/jsx-runtime";
|
|
|
6
7
|
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
7
8
|
import { useDataEngine, useFieldValue, useNamespace } from "@fumari/stf";
|
|
8
9
|
import { stringifyFieldKey } from "@fumari/stf/lib/utils";
|
|
9
|
-
import { sample } from "openapi-sampler";
|
|
10
10
|
//#region src/playground/schema.tsx
|
|
11
11
|
const SchemaContext = createContext(void 0);
|
|
12
12
|
const anyFields = {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { useTranslations } from "../ui/client/i18n.js";
|
|
2
|
+
import { useMemo } from "react";
|
|
1
3
|
import { CircleCheck, CircleX } from "lucide-react";
|
|
2
4
|
//#region src/playground/status-info.tsx
|
|
3
5
|
const statusKeys = {
|
|
@@ -27,30 +29,32 @@ const statusKeys = {
|
|
|
27
29
|
icon: CircleX
|
|
28
30
|
}
|
|
29
31
|
};
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
function useStatusInfo(status) {
|
|
33
|
+
const t = useTranslations();
|
|
34
|
+
return useMemo(() => {
|
|
35
|
+
if (status in statusKeys) {
|
|
36
|
+
const { key, color, icon } = statusKeys[status];
|
|
37
|
+
return {
|
|
38
|
+
description: t[key],
|
|
39
|
+
color,
|
|
40
|
+
icon
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (status >= 200 && status < 300) return {
|
|
44
|
+
description: t.statusSuccessful,
|
|
45
|
+
color: "text-green-500",
|
|
46
|
+
icon: CircleCheck
|
|
47
|
+
};
|
|
48
|
+
if (status >= 400) return {
|
|
49
|
+
description: t.statusError,
|
|
50
|
+
color: "text-red-500",
|
|
51
|
+
icon: CircleX
|
|
52
|
+
};
|
|
33
53
|
return {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
icon
|
|
54
|
+
color: "text-fd-muted-foreground",
|
|
55
|
+
icon: CircleX
|
|
37
56
|
};
|
|
38
|
-
}
|
|
39
|
-
if (status >= 200 && status < 300) return {
|
|
40
|
-
description: t.statusSuccessful,
|
|
41
|
-
color: "text-green-500",
|
|
42
|
-
icon: CircleCheck
|
|
43
|
-
};
|
|
44
|
-
if (status >= 400) return {
|
|
45
|
-
description: t.statusError,
|
|
46
|
-
color: "text-red-500",
|
|
47
|
-
icon: CircleX
|
|
48
|
-
};
|
|
49
|
-
return {
|
|
50
|
-
description: t.statusNoDescription,
|
|
51
|
-
color: "text-fd-muted-foreground",
|
|
52
|
-
icon: CircleX
|
|
53
|
-
};
|
|
57
|
+
}, [t, status]);
|
|
54
58
|
}
|
|
55
59
|
//#endregion
|
|
56
|
-
export {
|
|
60
|
+
export { useStatusInfo };
|
package/dist/scalar/client.js
CHANGED
|
@@ -4,13 +4,17 @@ import { MethodLabel } from "../ui/components/method-label.js";
|
|
|
4
4
|
import { useEffect, useState } from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
7
|
-
import {
|
|
7
|
+
import { useApiClient } from "@scalar/api-client-react";
|
|
8
8
|
import { useTheme } from "next-themes";
|
|
9
9
|
import "@scalar/api-client-react/style.css";
|
|
10
10
|
//#region src/scalar/client.tsx
|
|
11
11
|
function ScalarPlayground({ path, method, spec }) {
|
|
12
12
|
const { resolvedTheme } = useTheme();
|
|
13
13
|
const [mounted, setMounted] = useState(false);
|
|
14
|
+
const client = useApiClient({ configuration: {
|
|
15
|
+
theme: "moon",
|
|
16
|
+
spec
|
|
17
|
+
} });
|
|
14
18
|
useEffect(() => {
|
|
15
19
|
setMounted(true);
|
|
16
20
|
}, []);
|
|
@@ -25,33 +29,20 @@ function ScalarPlayground({ path, method, spec }) {
|
|
|
25
29
|
className: "flex-1 overflow-auto text-nowrap text-[0.8125rem] text-fd-muted-foreground",
|
|
26
30
|
children: path
|
|
27
31
|
}),
|
|
28
|
-
/* @__PURE__ */ jsx(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
/* @__PURE__ */ jsx("button", {
|
|
33
|
+
type: "submit",
|
|
34
|
+
className: cn(buttonVariants({
|
|
35
|
+
color: "primary",
|
|
36
|
+
size: "sm"
|
|
37
|
+
}), "px-3 py-1.5"),
|
|
38
|
+
onClick: () => client?.open({
|
|
34
39
|
path,
|
|
35
40
|
method
|
|
36
|
-
})
|
|
41
|
+
}),
|
|
42
|
+
children: "Test"
|
|
37
43
|
})
|
|
38
44
|
]
|
|
39
45
|
});
|
|
40
46
|
}
|
|
41
|
-
function Trigger({ path, method }) {
|
|
42
|
-
const client = useApiClientModal();
|
|
43
|
-
return /* @__PURE__ */ jsx("button", {
|
|
44
|
-
type: "submit",
|
|
45
|
-
className: cn(buttonVariants({
|
|
46
|
-
color: "primary",
|
|
47
|
-
size: "sm"
|
|
48
|
-
}), "px-3 py-1.5"),
|
|
49
|
-
onClick: () => client?.open({
|
|
50
|
-
path,
|
|
51
|
-
method
|
|
52
|
-
}),
|
|
53
|
-
children: "Test"
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
47
|
//#endregion
|
|
57
48
|
export { ScalarPlayground as default };
|
package/dist/ui/base.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parseSecurities } from "../utils/schema/index.js";
|
|
2
2
|
import { defaultAdapters } from "../requests/media/adapter.js";
|
|
3
|
-
import { encodeInternalRef } from "../utils/schema/ref.js";
|
|
4
3
|
import { ClientCodeBlockProvider } from "./components/codeblock.js";
|
|
4
|
+
import { encodeInternalRef } from "../utils/schema/ref.js";
|
|
5
5
|
import { APIPage } from "./api-page.js";
|
|
6
6
|
import { pickSchema } from "../utils/schema/pick.js";
|
|
7
7
|
import { PlaygroundAuthProvider } from "./client/boundary.lazy.js";
|
package/dist/ui/client/i18n.js
CHANGED
|
@@ -9,9 +9,11 @@ function useTranslations() {
|
|
|
9
9
|
* Renders a translated string. Use in server components so the label is resolved on the client from the current locale.
|
|
10
10
|
*/
|
|
11
11
|
function I18nLabel({ label, replacements = {} }) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
return withReplacements(useTranslations()[label], replacements);
|
|
13
|
+
}
|
|
14
|
+
function withReplacements(t, replacements) {
|
|
15
|
+
for (const [k, v] of Object.entries(replacements)) t = t.replaceAll(`{${k}}`, v);
|
|
16
|
+
return t;
|
|
15
17
|
}
|
|
16
18
|
//#endregion
|
|
17
|
-
export { I18nLabel, useTranslations };
|
|
19
|
+
export { I18nLabel, useTranslations, withReplacements };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { cn } from "../../utils/cn.js";
|
|
3
2
|
import { useTranslations } from "../client/i18n.js";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { X } from "lucide-react";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { cn } from "../../utils/cn.js";
|
|
3
2
|
import { useTranslations } from "../client/i18n.js";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
4
|
import { createContext, use, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { Check, Copy } from "lucide-react";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getPreferredType, pickExample } from "../../utils/schema/index.js";
|
|
2
2
|
import { encodeRequestData } from "../../requests/media/encode.js";
|
|
3
|
-
import { sample } from "
|
|
3
|
+
import { sample } from "../../utils/schema/sample.js";
|
|
4
4
|
//#region src/ui/operation/get-example-requests.ts
|
|
5
5
|
function getExampleRequests(path, operation, ctx) {
|
|
6
6
|
const requestBody = operation.requestBody;
|
|
@@ -2,9 +2,9 @@ import { idToTitle } from "../../utils/id-to-title.js";
|
|
|
2
2
|
import { createMethod, methodKeys } from "../../utils/schema/index.js";
|
|
3
3
|
import { isMediaTypeSupported } from "../../requests/media/resolve-adapter.js";
|
|
4
4
|
import "../../requests/media/adapter.js";
|
|
5
|
+
import { I18nLabel } from "../client/i18n.js";
|
|
5
6
|
import { cn } from "../../utils/cn.js";
|
|
6
7
|
import { Badge, MethodLabel } from "../components/method-label.js";
|
|
7
|
-
import { I18nLabel } from "../client/i18n.js";
|
|
8
8
|
import { CopyTypeScriptPanel, OperationProvider } from "./client.js";
|
|
9
9
|
import { Schema } from "../schema/index.js";
|
|
10
10
|
import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "../components/accordion.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveRequestData } from "../../utils/url.js";
|
|
2
|
-
import { MethodLabel } from "../components/method-label.js";
|
|
3
2
|
import { I18nLabel } from "../client/i18n.js";
|
|
3
|
+
import { MethodLabel } from "../components/method-label.js";
|
|
4
4
|
import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "../components/accordion.js";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "fumadocs-ui/components/tabs";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { getPreferredType } from "../../utils/schema/index.js";
|
|
2
2
|
import { I18nLabel } from "../client/i18n.js";
|
|
3
|
+
import { sample } from "../../utils/schema/sample.js";
|
|
3
4
|
import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "../components/accordion.js";
|
|
4
5
|
import { useMemo } from "react";
|
|
5
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { sample } from "openapi-sampler";
|
|
7
7
|
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
|
8
8
|
//#region src/ui/operation/response-tabs.tsx
|
|
9
9
|
function ResponseTabs({ operation, ctx }) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { joinURL, resolveRequestData, resolveServerUrl, withBase } from "../../../utils/url.js";
|
|
3
3
|
import { useApiContext, useServerContext } from "../../contexts/api.js";
|
|
4
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../components/select.js";
|
|
5
4
|
import { ClientCodeBlock } from "../../components/codeblock.js";
|
|
5
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../components/select.js";
|
|
6
6
|
import { useOperationContext } from "../client.js";
|
|
7
7
|
import { useEffect, useMemo, useState } from "react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
package/dist/ui/schema/client.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { useTranslations } from "../client/i18n.js";
|
|
2
3
|
import { cn } from "../../utils/cn.js";
|
|
3
4
|
import { Badge } from "../components/method-label.js";
|
|
4
|
-
import { useTranslations } from "../client/i18n.js";
|
|
5
5
|
import { Fragment, Suspense, createContext, use, useCallback, useDeferredValue, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { ChevronDown, FilterIcon } from "lucide-react";
|
|
8
|
+
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
8
9
|
import { cva } from "class-variance-authority";
|
|
9
10
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "fumadocs-ui/components/ui/collapsible";
|
|
10
|
-
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
11
11
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "fumadocs-ui/components/tabs";
|
|
12
12
|
import { Popover, PopoverContent, PopoverTrigger } from "fumadocs-ui/components/ui/popover";
|
|
13
13
|
//#region src/ui/schema/client.tsx
|
package/dist/ui/schema/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { I18nLabel } from "../client/i18n.js";
|
|
1
2
|
import { mergeAllOf } from "../../utils/schema/merge.js";
|
|
2
3
|
import { FormatFlags, schemaToString } from "../../utils/schema/to-string.js";
|
|
3
|
-
import { I18nLabel } from "../client/i18n.js";
|
|
4
4
|
import { useMemo } from "react";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region src/ui/schema/index.tsx
|