[openapi-fetch] Provide `client.request()` to support dynamic method.
Description
Currently, openapi-fetch uses the method as the function name (ex: client.GET()) and there is no way to use the method as an argument. When building around openapi-fetch it requires a bit of gymnastic and manual typing to have a dynamic method.
const mth = method.toUpperCase() as keyof typeof client;
const fn = client[mth] as ClientMethod<Paths, typeof method, Media>;
We can also find this pattern in libraries like axios, ky, etc.
Proposal
Internally, openapi-fetch already use coreFetch method to pass the method as an argument.
We could have a request (or REQUEST to respect casing) method on the client. (or FETCH).
return {
/** Call an endpoint */
async REQUEST(method, url, init) {
return coreFetch(url, { ...init, method });
}
/** Call a GET endpoint */
async GET(url, init) {
return coreFetch(url, { ...init, method: "GET" });
},
/** Call a PUT endpoint */
async PUT(url, init) {
return coreFetch(url, { ...init, method: "PUT" });
},
/** Call a POST endpoint */
async POST(url, init) {
return coreFetch(url, { ...init, method: "POST" });
},
[...]
}
Checklist
- [x] I’m willing to open a PR for this (see CONTRIBUTING.md)
I’d be open to adding this! This should be pretty invisible. There’s no strong reason this wasn’t done initially. But one trickiness in all this will be requiring (or denying) requestBody based on the method. We’ll need lots of type tests to make sure this catches everything (negative type tests are as valuable as—if not moreso—positive type tests). But adding this should be very doable and shouldn’t impact performance at all.
I’d be open to adding this as well! In the case where we need to isolate the backend for security reasons, we will make an api proxy on the React server side, so that all client's query goes through the api proxy to make the request. In the case where openapi-fetch is to be executed in the proxy instead of directly on the client, request method should be passed as a variable to achieve a generic proxy.
In this usage scenario, there is also the problem of not being able to dynamically assign a value to path parameter, because of its PathsWithMethod type definition. Perhaps the dynamic assignment of path can be achieved by throwing an error when path doesn't match paths with methods, while balancing the efficiency of checking with PathsWithMethod.
I have been trying to implement
const mth = method.toUpperCase() as keyof typeof client;
const fn = client[mth] as ClientMethod<Paths, typeof method, Media>;
Could you provide a full example with method, Paths and Media defined?
I have been trying to get it work, however typescript throws obscure errors at me.