Skip to content

204 response causes wrong data to be undefined #1933

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1 task
DjordyKoert opened this issue Oct 1, 2024 · 3 comments · Fixed by #1937
Closed
1 task

204 response causes wrong data to be undefined #1933

DjordyKoert opened this issue Oct 1, 2024 · 3 comments · Fixed by #1937
Labels
bug Something isn't working good first issue Straightforward problem, solvable for first-time contributors without deep knowledge of the project openapi-fetch Relevant to the openapi-fetch library PRs welcome PRs are welcome to solve this issue!

Comments

@DjordyKoert
Copy link
Contributor

DjordyKoert commented Oct 1, 2024

Description

Having a 204 response in combination with a 200 response in the generated type causes the returned data to become undefined

image

Generated openapi.ts file by openapi-typescript:

export interface operations {
    get_getOrdersByCustomerId: {
        parameters: {
            query?: {
                /** @description Limit the amount of orders returned */
                limit?: number;
                /** @description Offset results */
                offset?: number;
            };
            header?: never;
            path: {
                customerId: string;
            };
            cookie?: never;
        };
        requestBody?: never;
        responses: {
            /** @description Returns all orders for a customer */
            200: {
                headers: {
                    [name: string]: unknown;
                };
                content: {
                    "application/json": components["schemas"]["OrderDTO"][];
                };
            };
            /** @description No orders found for customer */
            204: {
                headers: {
                    [name: string]: unknown;
                };
                content?: never;
            };
        };
    };
}

Reproduction

Have an operation as defined above (with a 200 and a 204 with no content). Then attempt to use the openapi-fetch client for the operation.

Expected result

I expected the type a union of components["schemas"]["OrderDTO"][] | undefined and for me to not have to do a manual type assertion.

export type UseOpenApiFetchHookOptions<
    T extends keyof paths,
    TMethod extends keyof paths[T],
    TOperation extends paths[T][TMethod] = paths[T][TMethod],
> = ParamsOption<TOperation> & RequestBodyOption<TOperation> & {
    // add your custom options here
    reactQuery?: {
        enabled: boolean; // Note: React Query type’s inference is difficult to apply automatically, hence manual option passing here
        // add other React Query options as needed
    };
};

const getCustomerOrders: keyof paths = '/api/v1/customers/{customerId}/orders';
export const customerOrdersOptions = ({ params }: UseOpenApiFetchHookOptions<typeof getCustomerOrders, 'get'>) => queryOptions({
    placeholderData: keepPreviousData,
    queryFn: async ({ signal }) => {
        const { data, response } = await client.GET('/api/v1/customers/{customerId}/orders', {
            params,
            parseAs: 'json',
            signal,
        });

        if (!response.ok) {
            throw 'error';
        }

        if (response.status === 204) { // Unrelated, Fix for 204's returning an empty object {}
            return null;
        }

        return data as unknown as Array<components['schemas']['OrderDTO']>; // Assertion should not be needed here
    },
    queryKey: [
        getCustomerOrders,
        params,
    ],
});

Checklist

@DjordyKoert DjordyKoert added bug Something isn't working openapi-fetch Relevant to the openapi-fetch library labels Oct 1, 2024
@drwpow drwpow added PRs welcome PRs are welcome to solve this issue! good first issue Straightforward problem, solvable for first-time contributors without deep knowledge of the project labels Oct 1, 2024
@drwpow
Copy link
Contributor

drwpow commented Oct 1, 2024

Thanks for raising! This is definitely a bug. It’s caused by a | never in the union that throws a wrench into the type inference, but this should be avoidable. Possibly even with a NonNullable<T> wrapping the data

@gbudiman
Copy link

gbudiman commented Oct 1, 2024

Came here to report similar issue. I noticed this started showing when upgrading openapi-fetch to 0.10.0 or higher (latest 0.12.x also affected).

Using openapi-typescript 7.4.1

@samuelpucat
Copy link

Hi, I have a similar problem

generated schema.d.ts:

export interface operations {
    ...
    deleteLoadBalancer: {
        parameters: { ... };
        requestBody?: never;
        responses: {
            /** @description OK */
            200: {
                headers: {
                    [name: string]: unknown;
                };
                content?: never;
            };
        };
    };
    ...
}

calling api:

const { data } = await client.DELETE('/load-balancers/{name}', {
    params: {
        header: { correlationId: generateCorrelationId() },
        path: { name: loadBalancerName },
        query: { projectId },
    },
    // parseAs: 'text',
});

throws error:

SyntaxError: Unexpected end of JSON input
    at u (index.js:164:44)

which is in this part of library:

// parse response (falling back to .text() when necessary)
if (response.ok) {
  // if "stream", skip parsing entirely
  if (parseAs === "stream") {
    return { data: response.body, response };
  }
  return { data: await response[parseAs](), response };      // line 164
}

Calling the API with parseAs: 'text', solves the error but I don't know whether it is the correct solution
I feel like this should have been caught by this:

// handle empty content
if (response.status === 204 || response.headers.get("Content-Length") === "0") {
  return response.ok ? { data: undefined, response } : { error: undefined, response };
}

but this API doesn't return Content-Length header nor have 204 status

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Straightforward problem, solvable for first-time contributors without deep knowledge of the project openapi-fetch Relevant to the openapi-fetch library PRs welcome PRs are welcome to solve this issue!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants