mnahkies / openapi-code-generator

A code generation tool for openapi 3 / 3.1 specifications written in typescript, primarily aimed at generating typescript clients and server stubs. Other target languages may be added in future.
https://openapi-code-generator.nahkies.co.nz/
MIT License
16 stars 2 forks source link

GET request list parameters not handled correctly #217

Open codemedian opened 1 month ago

codemedian commented 1 month ago

Hi,

I have an OpenAPI operation that looks as follows

 "/test/array": {
            "get": {
                "operationId": "ArrayTest",
                "parameters": [
                    {
                        "name": "value",
                        "in": "query",
                        "style": "form",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        },
                        "explode": true
                    }
                ],
                "responses": {

                }
            }
        },

In my understanding, this should support one or many string elements passed to it in the query, so both the below queries should be considered correct

  1. .../test/array?value=foo => ["foo"]
  2. .../test/array?value=foo&value=bar => ["foo", "bar"]

When running this however, the single element variant fails validation in the middleware which I think is a bug?

Thanks Chris

mnahkies commented 1 month ago

I assume this is typescript-koa that you're bumping into this?

I suspect what is happening is that ctx.query.value is probably either string or string[] depending on whether a single value or multiple have been passed - since we can't pass any runtime hinting directly to the query string parser :(

I guess the fix would be to account for this by making the zod schema a union of T | T[] which may be slightly nasty to achieve just for the query parameter parsing, but I'll have a look.

mnahkies commented 1 month ago

I've put a WIP solution up here https://github.com/mnahkies/openapi-code-generator/pull/220

It essentially changes it to accept a T | T[] and then normalize a T -> T[] such that your code will always see an array, regardless of whether it is a single element or multiple to save tedious Array.isArray checks on the consuming side.

To achieve this I've added a x-alpha-transformation extension, which needs a little more thought and integration - it might need to be something more like:

x-alpha-transformation:
  fn: it => it === undefined || Array.isArray(it) ? it : [it]
  type: string[]

To make the extension more generally useful, as at the moment there is no way to tell the type-builder what your transformation function returns, and so it's just by good luck that it works for this use-case.

I'm a bit time poor this weekend, so might not get this completed for a few days.

codemedian commented 1 month ago

Ah, sorry, should have added more context 😕

Yeah, it's in typescript-koa. Sounds plausible that it'd be a string or array, yeah. Don't really have a good idea on how to handle it without runtime type hints, the T | T[] seems like a good opinion though

Thank you!