OpenAPI: Improve FormData implementation

This commit is contained in:
fuma-nama
2024-07-31 16:49:01 +08:00
parent dfcc61f9a9
commit f2b540a561
5 changed files with 32 additions and 35 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-openapi': patch
---
Fix `fetch` problems on API Playground
+4 -1
View File
@@ -173,7 +173,7 @@ paths:
requestBody:
required: true
content:
application/json:
multipart/form-data:
schema:
$ref: '#/components/schemas/BuyMuseumTicketsRequest'
examples:
@@ -255,6 +255,9 @@ components:
$ref: '#/components/schemas/Email'
phone:
$ref: '#/components/schemas/Phone'
image:
type: string
format: binary
required:
- ticketType
- ticketDate
+18 -29
View File
@@ -12,51 +12,38 @@ export function createBodyFromValue(
schema: RequestSchema,
references: Record<string, RequestSchema>,
dynamic: Map<string, DynamicField>,
): unknown {
): string | FormData {
const result = convertValue('body', value, schema, references, dynamic);
if (type === 'json') {
return convertValue('body', value, schema, references, dynamic);
return JSON.stringify(result);
}
const formData = new FormData();
if (schema.type !== 'object' || typeof value !== 'object' || !value) {
if (typeof result !== 'object' || !result) {
throw new Error(
`Unsupported body schema type: ${schema.type}, expected: object`,
`Unsupported body type: ${typeof result}, expected: object`,
);
}
for (const key of Object.keys(value)) {
if (!(key in schema)) return;
for (const key of Object.keys(result)) {
const prop: unknown = result[key as keyof object];
const prop = resolve(schema.properties[key], references);
if (prop.type === 'file') {
formData.set(key, value[key as keyof object]);
if (typeof prop === 'object' && prop instanceof File) {
formData.set(key, prop);
}
if (
prop.type === 'array' &&
Array.isArray(value) &&
resolve(prop.items, references).type === 'file'
) {
for (const item of value) {
formData.append(key, item as Blob);
if (Array.isArray(prop) && prop.every((item) => item instanceof File)) {
for (const item of prop) {
formData.append(key, item);
}
}
formData.set(
key,
JSON.stringify(
convertValue(
`body.${key}`,
value[key as keyof object],
resolve(schema.properties[key], references),
references,
dynamic,
),
),
);
formData.set(key, JSON.stringify(prop));
}
return formData;
}
/**
@@ -133,6 +120,8 @@ function convertValue(
return Number(value);
case 'boolean':
return value === 'null' ? undefined : value === 'true';
case 'file':
return value; // file
default:
return String(value);
}
+3 -3
View File
@@ -435,15 +435,15 @@ function NormalInput({
<FormField
control={control}
name={fieldName}
render={({ field: { value, onChange, ...restField } }) => (
render={({ field: { value: _value, onChange, ...restField } }) => (
<FormItem {...props}>
{header}
<p>{(value as File | undefined)?.name}</p>
<FormControl>
<input
type="file"
multiple={false}
onChange={(e) => {
if (!e.target.files) return [];
if (!e.target.files) return;
onChange(e.target.files.item(0));
}}
{...restField}
+2 -2
View File
@@ -94,7 +94,7 @@ export function APIPlayground({
pathname = pathname.replace(`{${key}}`, paramValue);
});
const url = new URL(pathname, baseUrl ?? window.location.origin);
const url = new URL(`${baseUrl ?? window.location.origin}${pathname}`);
Object.keys(input.query).forEach((key) => {
const paramValue = input.query[key];
if (typeof paramValue === 'string')
@@ -128,7 +128,7 @@ export function APIPlayground({
const response = await fetch(url, {
method,
headers,
body: bodyValue ? JSON.stringify(bodyValue) : undefined,
body: bodyValue,
});
const data: unknown = await response.json().catch(() => undefined);