w3cj / hono-open-api-starter

A starter template for building fully documented type-safe JSON APIs with Hono and Open API
https://www.youtube.com/watch?v=sNh9PoM9sUE
MIT License
328 stars 34 forks source link

Types don't get infer on client #4

Closed enyelsequeira closed 1 month ago

enyelsequeira commented 1 month ago

Hey @w3cj I watched the video and loved the starter, I tried using it in a monorepo like setup, but the types of the app router don't get infer correctly in the client which is just a vite react application, wondering if you have any workaround it? using somehting like this

import { Hono } from 'hono'
import authors from './authors'

const booksApp = new Hono()
  .get("/", (c) => c.json({ result: "list books" }))
  .post("/", (c) => c.json({ result: "create a book" }, 201))
  .get("/:id", (c) => c.json({ result: `get ${c.req.param("id")}` }));

const app = new Hono()

const routes = app.route('/authors', authors).route('/books', books)

export default app
export type AppType = typeof routes

this does infer the types correctly, but only infers books, routes ans not the authors, because it lives in another file. wondering if you have any idea as to why that might be? image image but then for books you can see that it does get infer correctly, since its in the same file. I also tried openAI and that just doesnt give any inference at all, any suggestions?

Thank you!

w3cj commented 1 month ago

Can you show the authorsApp export? You need to make sure that the exported value includes the chained methods, just like the booksApp variable.

Notice how in my tasks example, the exported router is the full chain, not just the hono app: https://github.com/w3cj/hono-open-api-starter/blob/main/src/routes/tasks/tasks.index.ts#L13

enyelsequeira commented 1 month ago

Can you show the authorsApp export? You need to make sure that the exported value includes the chained methods, just like the booksApp variable.

Notice how in my tasks example, the exported router is the full chain, not just the hono app: https://github.com/w3cj/hono-open-api-starter/blob/main/src/routes/tasks/tasks.index.ts#L13

yes, of course. I am chaining them similar to the books one. Only difference is that it is in another file

image

w3cj commented 1 month ago

Ah gotcha. The calls need to be one after another like new Hono().get().post().get() etc. otherwise you lose the type information.

So this needs to be:

const app = new Hono()
  .get("/", ...)
  .post("/", ...)
  .get("/:id", ...)

export default app;
enyelsequeira commented 1 month ago

I was following this https://hono.dev/docs/guides/best-practices, guess it shouldn't be as the docs in here. this does in fact get the types correctly.

//GETS TYPES CORRECTLY
const app = new Hono()
  .get("/", ...)
  .post("/", ...)
  .get("/:id", ...)

export default app;

Would you have any idea why then for example when using the setup you have, exactly the same the client is unable to get the type correctly? image image

i've created a repo showcasing this here https://github.com/enyelsequeira/Demo-honojs-vite-react

w3cj commented 1 month ago

Not sure, but in a typical monorepo setup, the dependent package folders are next to each other, not nested. Then instead of creating typescript aliases to the other projects, the projects list each other as dependencies and can import directly from the project package name.

For a proper setup, checkout workspaces: https://pnpm.io/workspaces

Something else to try, if you can get your server code building with typescript (with declaration files), you can import the built declaration type directly into the frontend.

enyelsequeira commented 1 month ago

Not sure, but in a typical monorepo setup, the dependent package folders are next to each other, not nested. Then instead of creating typescript aliases to the other projects, the projects list each other as dependencies and can import directly from the project package name.

For a proper setup, checkout workspaces: https://pnpm.io/workspaces

Something else to try, if you can get your server code building with typescript (with declaration files), you can import the built declaration type directly into the frontend.

Hey Cj. Thank you I will try to change it to a monorepo setup either using what you shared or turborepo and see if the issue still occurs :)