openapi-generator
openapi-generator copied to clipboard
[BUG] typescript-fetch casts enum scalar values to Blob
Description
Currently, when the OpenAPI declaration file is being generated, the open-api-generator treats enum values (which are scalars, such as string and numbers) as complex, object-like structures in insists of casting them to Blob as a part of the multipart/form-data
request payload.
openapi-generator version
5.3.1
OpenAPI declaration file content or url
This is the output from the FASTApi application, an endpoint expecting a multipart/form-data
request with both file and some "metadata" describing this file.
(...)
"components": {
"schemas": {
"Body_create_upload_form_data_request": {
"title": "Body_create_upload_form_data_request",
"required": [
"file_type",
"some_prop_1",
],
"type": "object",
"properties": {
"source_file": {
"title": "Source File",
"type": "string",
"format": "binary"
},
"file_type": {
"$ref": "#/components/schemas/FileType"
},
"some_prop_1": {
"title": "Some Prop",
"type": "string"
},
}
},
(...)
"FileType": {
"title": "FileType",
"enum": [
"MY_FILE_TYPE_1",
"MY_FILE_TYPE_2",
"MY_FILE_TYPE_3",
],
"type": "string",
"description": "An enumeration."
},
(...)
Generation Details
The command-line script to run the docker container with open-api generator
docker run --add-host=host.docker.internal:host-gateway --rm \
--user $(id -u):$(id -g) \
-v "${PWD}:/local" openapitools/openapi-generator-cli:v5.3.1 generate \
-i http://host.docker.internal/api/v1/openapi.json \ # all containers are run in the same docker-compose network, hence the address
-g typescript-fetch \
--additional-properties=typescriptThreePlus=true \
-o /som/dir
The output of the generated code:
export enum FileType {
MyFileType1 = 'MY_FILE_TYPE_1',
MyFileType2 = 'MY_FILE_TYPE_1',
MyFileType3 = 'MY_FILE_TYPE_1',
}
if (requestParameters.fileType !== undefined) {
formParams.append(
'file_type', new Blob(
[JSON.stringify(FileTypeToJSON(requestParameters.fileType))],
{ type: "application/json" }
)
);
}
Steps to reproduce
Create an appropriate data structure in your code so that it leads to the OpenAPI declaration output as shown above
Suggest a fix
Treat enum value as a primitive and allow it to be directly taken as an argument for formData in multipart/form-data
requests.
if (requestParameters.fileType !== undefined) {
formParams.append('file_type', requestParameters.fileType as any);
}
The same problem happens when I want to send an object as JSON to the backend. Without the SDK I would just
formData.append('files'. JSON.stringify(data))
. I don't see the point of having new Blob()
there
new Blob()
makes "multerjs" fails also. Because it thinks the the json is a file and I didn't specified the field with the json to be a file inside the multer configuration
Im having issues with this also. I was able to get it working for my needs with a workaround, but I would much rather this handle it properly and generate the client code cleanly. If anyone is curious, here is the workaround I used. It essentially unravels the Blob wrapper around the enum to get the string value in a middleware.
async function ResolveAssetTypeEnumMiddleware(context: RequestContext) {
const { body } = context.init;
if (body && body instanceof FormData) {
const type = body.get("type");
if (type instanceof File) {
const jsonType = await type.text();
const resolvedType = JSON.parse(jsonType);
body.set("type", resolvedType);
}
}
return context;
}
const assetsApi = new AssetsApi(tokenApiConfig).withPreMiddleware(
ResolveAssetTypeEnumMiddleware
);
@zmrl010 Thanks!
BTW, if you have multiple types to handle:
async function resolveEnumTypes(context: RequestContext) {
const { body } = context.init;
if (body && body instanceof FormData) {
for (const key of ["amazing_type1", "amazing_type2"]) {
const type = body.get(key);
if (type instanceof File) {
const jsonType = await type.text();
const resolvedType = JSON.parse(jsonType);
body.set(key, resolvedType);
}
}
}
return context;
}
Confirmed this with 6.2.1 have the same issue
Request Interface
export interface EmployeesPatchRequestParams {
/** A unique integer value identifying this User. */
id: number;
/** Company ID for which employees should be filtered. */
company_id?: number;
position?: string | null;
lang?: PatchedUserPatchRequestLang | null;
}
implementation
if (lang !== undefined) {
localVarFormParams =
(localVarFormParams.append(
'lang',
localVarUseForm ? new Blob([JSON.stringify(lang)], { type: 'application/json' }) : <any>lang
) as any) || localVarFormParams;
}
swagger
"PatchedUserRequest": {
"type": "object",
"properties": {
"position": {
"type": "string",
"nullable": true,
"maxLength": 256
},
"lang": {
"nullable": true,
"oneOf": [
{
"$ref": "#/components/schemas/LangEnum"
},
{
"$ref": "#/components/schemas/BlankEnum"
},
{
"$ref": "#/components/schemas/NullEnum"
}
]
},
Same problem with multipart/form-data When i try to send files and json string as form-data key-value openapi-generator-cli add new Blob
openapi-generator-cli version 6.5.0
swagger.json
"requestBody": {
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"properties": {
"request": {
"$ref": "#/components/schemas/MySchema"
},
"files": {
"type": "array",
"items": {
"type": "string",
"format": "binary"
}
}
}
},
generated code:
if (request !== undefined) {
localVarFormParams.append('request', new Blob([JSON.stringify(request)], { type: "application/json", }));
}
if (files) {
files.forEach((element) => {
localVarFormParams.append('files', element as any);
})
}
Fix it please
Also hoping in. How it is currently done, requests fail on mobile devices using React-Native with fetch. Treating enum values as scalar values fixes it.
if (requestParameters.type !== undefined) {
formParams.append('type', requestParameters.type as any);
}