question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] typescript-fetch casts enum scalar values to Blob

See original GitHub issue
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);
}

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:5

github_iconTop GitHub Comments

3reactions
zmrl010commented, Apr 12, 2022

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
);
0reactions
finchacommented, Dec 1, 2022

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"
                            }
                        ]
                    },
Read more comments on GitHub >

github_iconTop Results From Across the Web

The trouble with TypeScript enums - Thoughtbot
In TypeScript, enums have a few surprising limitations. In particular, it can be challenging to check whether or not a value is in...
Read more >
TypeScript TS7015 error when accessing an enum using a ...
Using keyof allows us to assert that the property is indeed in the target object. However, when you create an enum, TypeScript actually...
Read more >
Enums - TypeGraphQL
Enums limit the range of a variable's values to a set of predefined constants, which makes it easier to document intent. GraphQL also...
Read more >
Backed enumerations - Manual - PHP
A case that has a scalar equivalent is called a Backed Case, as it is "Backed" by a simpler value. An Enum that...
Read more >
Why TypeScript enums suck - LogRocket Blog
In your database, you may have this value stored as a number. By defining it as a TypeScript enum, we can cast it...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found