Skip to content

Commit d8c9944

Browse files
authored
Merge pull request #50 from dev-five-git/fix-formdata
Fix formdata issue
2 parents 1b25a8f + 05322e3 commit d8c9944

File tree

4 files changed

+66
-20
lines changed

4 files changed

+66
-20
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"changes":{"packages/generator/package.json":"Patch"},"note":"Fix Formdata issue","date":"2026-02-18T18:18:07.532985400Z"}

examples/next/app/page.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ export default function Home() {
9797
tags: 'tag1,tag2',
9898
},
9999
})
100+
101+
api3.POST('/typed-form', {
102+
body: new FormData(),
103+
})
100104
}, [mutateAsync])
101105
return (
102106
<Box>

packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1834,13 +1834,13 @@ declare module "@devup-api/fetch" {
18341834
interface DevupPostApiStruct {
18351835
'openapi.json': {
18361836
'/form': {
1837-
body: DevupObject<'request', 'openapi.json'>['SubscribeRequest'];
1837+
body: DevupObject<'request', 'openapi.json'>['SubscribeRequest'] | FormData;
18381838
response?: {
18391839
ok?: boolean;
18401840
};
18411841
};
18421842
subscribe: {
1843-
body: DevupObject<'request', 'openapi.json'>['SubscribeRequest'];
1843+
body: DevupObject<'request', 'openapi.json'>['SubscribeRequest'] | FormData;
18441844
response?: {
18451845
ok?: boolean;
18461846
};
@@ -1875,19 +1875,19 @@ declare module "@devup-api/fetch" {
18751875
interface DevupPostApiStruct {
18761876
'openapi.json': {
18771877
'/form/contact': {
1878-
body?: {
1879-
name?: string;
1880-
email?: string;
1881-
message?: string;
1882-
};
1878+
body: {
1879+
name?: string;
1880+
email?: string;
1881+
message?: string;
1882+
} | FormData;
18831883
response?: {};
18841884
};
18851885
contact: {
1886-
body?: {
1887-
name?: string;
1888-
email?: string;
1889-
message?: string;
1890-
};
1886+
body: {
1887+
name?: string;
1888+
email?: string;
1889+
message?: string;
1890+
} | FormData;
18911891
response?: {};
18921892
};
18931893
}
@@ -1913,13 +1913,13 @@ declare module "@devup-api/fetch" {
19131913
interface DevupPostApiStruct {
19141914
'openapi.json': {
19151915
'/typed-form': {
1916-
body: DevupObject<'request', 'openapi.json'>['CreateFileUploadRequest'];
1916+
body: DevupObject<'request', 'openapi.json'>['CreateFileUploadRequest'] | FormData;
19171917
response?: {
19181918
id?: string;
19191919
};
19201920
};
19211921
createFileUpload: {
1922-
body: DevupObject<'request', 'openapi.json'>['CreateFileUploadRequest'];
1922+
body: DevupObject<'request', 'openapi.json'>['CreateFileUploadRequest'] | FormData;
19231923
response?: {
19241924
id?: string;
19251925
};
@@ -1993,14 +1993,14 @@ declare module "@devup-api/fetch" {
19931993
params: {
19941994
id: string;
19951995
};
1996-
body: DevupObject<'request', 'openapi.json'>['UpdateFileUploadRequest'];
1996+
body: DevupObject<'request', 'openapi.json'>['UpdateFileUploadRequest'] | FormData;
19971997
response?: {};
19981998
};
19991999
updateFileUpload: {
20002000
params: {
20012001
id: string;
20022002
};
2003-
body: DevupObject<'request', 'openapi.json'>['UpdateFileUploadRequest'];
2003+
body: DevupObject<'request', 'openapi.json'>['UpdateFileUploadRequest'] | FormData;
20042004
response?: {};
20052005
};
20062006
}
@@ -2012,14 +2012,14 @@ declare module "@devup-api/fetch" {
20122012
params: {
20132013
id: string;
20142014
};
2015-
body: DevupObject<'request', 'openapi.json'>['PatchFileUploadRequest'];
2015+
body: DevupObject<'request', 'openapi.json'>['PatchFileUploadRequest'] | FormData;
20162016
response?: {};
20172017
};
20182018
patchFileUpload: {
20192019
params: {
20202020
id: string;
20212021
};
2022-
body: DevupObject<'request', 'openapi.json'>['PatchFileUploadRequest'];
2022+
body: DevupObject<'request', 'openapi.json'>['PatchFileUploadRequest'] | FormData;
20232023
response?: {};
20242024
};
20252025
}
@@ -2064,11 +2064,11 @@ declare module "@devup-api/fetch" {
20642064
response?: {};
20652065
};
20662066
'/form': {
2067-
body: DevupObject<'request', 'openapi.json'>['SubscribeRequest'];
2067+
body: DevupObject<'request', 'openapi.json'>['SubscribeRequest'] | FormData;
20682068
response?: {};
20692069
};
20702070
subscribe: {
2071-
body: DevupObject<'request', 'openapi.json'>['SubscribeRequest'];
2071+
body: DevupObject<'request', 'openapi.json'>['SubscribeRequest'] | FormData;
20722072
response?: {};
20732073
};
20742074
'/form/upload': {

packages/generator/src/generate-interface.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
getRequestBodyContent,
1717
isErrorStatusCode,
1818
normalizeServerName,
19+
resolveRef,
1920
} from './openapi-utils'
2021
import { wrapInterfaceKeyGuard } from './wrap-interface-key-guard'
2122

@@ -117,6 +118,30 @@ function extractContentType(
117118
return extractInlineType(jsonContent.schema)
118119
}
119120

121+
/**
122+
* Check if a request body uses form or multipart content type.
123+
*/
124+
function isFormOrMultipartRequestBody(
125+
requestBody: OpenAPIV3_1.RequestBodyObject | OpenAPIV3_1.ReferenceObject,
126+
document: OpenAPIV3_1.Document,
127+
): boolean {
128+
let content: OpenAPIV3_1.RequestBodyObject['content'] | undefined
129+
if ('$ref' in requestBody) {
130+
const resolved = resolveRef<OpenAPIV3_1.RequestBodyObject>(
131+
requestBody.$ref,
132+
document,
133+
)
134+
content = resolved?.content
135+
} else {
136+
content = requestBody.content
137+
}
138+
if (!content) return false
139+
return (
140+
content['multipart/form-data'] !== undefined ||
141+
content['application/x-www-form-urlencoded'] !== undefined
142+
)
143+
}
144+
120145
// Generate interface for a single schema
121146
function generateSchemaInterface(
122147
schema: OpenAPIV3_1.Document,
@@ -346,6 +371,22 @@ function generateSchemaInterface(
346371
}
347372
}
348373
if (requestBodyType !== undefined) {
374+
// For form/multipart endpoints, also allow FormData as body type
375+
if (operation.requestBody) {
376+
const isFormMultipart = isFormOrMultipartRequestBody(
377+
operation.requestBody,
378+
schema,
379+
)
380+
if (isFormMultipart) {
381+
const bodyStr =
382+
typeof requestBodyType === 'string'
383+
? requestBodyType
384+
: formatTypeValue(requestBodyType)
385+
if (!bodyStr.includes('FormData')) {
386+
requestBodyType = `${bodyStr} | FormData`
387+
}
388+
}
389+
}
349390
endpoint.body = requestBodyType
350391
}
351392

0 commit comments

Comments
 (0)