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
Pure RPC client types #2489
Comments
How a found a little way to make this work: Below is a pure type that does not care about the contents of route implementation. For now I am just going to create a separate library with such types for each router... export type AppType = Hono<
Env,
ToSchema<
'get',
'/hello',
{
query: {
test: string;
};
},
Promise<
TypedResponse<{
hello: string;
}>
>
>,
'/'
>;
const client = hc<AppType>('localhost');
client.hello.$get({ query: { test: 'hello' } }); |
I tried the same thing but with const route = createRoute({
method: 'get',
path: '/hello',
request: {
params: z.object({ test: z.string() }),
},
responses: {
200: {
content: {
'application/json': {
schema: z.object({ hello: z.literal('world') }),
},
},
description: 'Get hello!',
},
},
});
const api = new OpenAPIHono();
const APP = api.openapi(route, function () {} as any);
const client = hc<typeof APP>('localhost');
const req = await client.hello.$get({ param: { test: '123123' } });
const res = await req.json();
// === "world"
console.log(res.hello) This gave me full control over the types I have in my client, so I managed to create a whole client without any actual code. This same |
Hi @askorupskyy Is the matter resolved? If not, please provide a minimal project to reproduce it. I'll investigate. |
I'll make a project and tag you in a couple hrs. I found a hack around original Hono type behavior but this would be nice to have as a part of the framework. This little hack that I put above worked for me and actually reduced the amount of |
https://github.com/askorupskyy/hono-rpc-types I created a simple project that explains the issue. Follow the README and the code |
Thanks! |
I read through some more issues and I think using my proposal would also fix #1921. Seems like one of the cases I covered in the README to my repo |
Hmm. I'm trying it, but I'm not so familiar with Nx, and I can't understand what causes the issue. I think it's fine to simply make it emit |
@yusukebe Nx in my case is just used to demonstate some of the bugs the current type system might cause. The main problem is Hono client needs to infer all the types from routes directly, which causes all of the code inside At my company we've been using tRPC which had a similar issue. It was building too many types and causing our builds to fail due to lack of RAM. We later switched to ts-rest, which creates the types in advance, similar to what #1921 is proposing,
Essentially what I did in this repo is a created the It would be nice to declare your route types in Hono the same way as in ts-rest. |
This syntax would work better: // declare a router
const createUserRouter = createRouter({
method: 'POST',
input: // either a TS type or a zod object
output: // just a TS type
}) // implement a router
// use generics to make sure what you are implementing matches the type of the declaration
const router = new Hono().post<typeof createUserRouter>('/user', (c) => c.json(new User())) // create a client
const client = hc<typeof createUserRouter>(); This way the client only depends on the type of the declaration, not the entire business logic of the app. |
@askorupskyy Thanks for explanation. In the future, we may add a Validator that validates Response (#2439), so if we can infer the type from that Validator, we will not need to generate the type from the entire Hono application. |
Either way, this is not a problem that can be solved right away. I'd like to take some time to think about it. |
Plus. As you @askorupskyy mentioned above, the one way to solve this issue is using Zod OpenAPI. Because it is designed to declare endpoint types explicitly. So, we may not have to make Hono core's type inferences more complicated to support this matter. Just use Zod OpenAPI. |
@yusukebe thank you so much! i did not initially realize zod-openapi resolves this matter completely |
@yusukebe, I believe this change may have broken ZodOpenAPI type inferrence: |
What is the feature you are proposing?
The problem
I was using Hono for one of my monorepo projects and one of the problems I have is that it fails to compile whenever the process environments are different.
Some to code to better explain:
API environment
This below contains all sorts of stuff the API might need, like DB connection strings, payment credentials...
Nextjs web client environment
Compile issues:
How since the Hono RPC client is just the representation of the API, it should not care for missing environment type definitions on the backend.
However, when compiled, (I use
Nx
withesbuild
), the frontend application complains about missing backend environment types, even though this stuff should be abstracted.I should not need the
REDIS_URL
to be inprocess.env
within my Nextjs app, however, Hono makes me do this...Possible fix:
Now I've done some digging and it does not make sense to build ALL of the routes, including their actual implementations in order to have a client type.
It would make much more sense to have a
route type
, aka input->output definition, from which the client would be constructed. The actual routers would then import this type and have the actual logic.This, in pair with
zod-openapi
package would make Hono a killer RPC platform.How do Hono's competitors achieve this?
I've also been using https://ts-rest.com/, which follows pretty much the same pattern I'm proposing here. The only difference is ts-rest follows full OpenAPI specs for their API definitions.
For example,
This code below describes the type of the router (the client inherits directly from here...)
The text was updated successfully, but these errors were encountered: