Is app.route
supported for rpc?
#2256
-
Hi, Let's I have the following code: // books.ts
import { Hono } from "hono";
const books = new Hono();
books.get("/", (c) => c.json({ message: "books" }));
export default books; // main.ts
import { Hono } from "hono";
import { hc } from "hono/client";
import books from "./books";
const routes = app
.get("/", (c) => c.json({ message: "hi" }))
.route("/api/book", books);
const client = hc<typeof routes>("http://localhost:5173");
client // only `.index` exists here, no `.api.books` :( I can not get |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
Hi |
Beta Was this translation helpful? Give feedback.
-
That's a bummer.
// books.ts
import type { Hono } from "hono";
export function addBookRoutes(app: Hono) {
return app
.post("api/book", (c) => c.json({ key: "123", title: "Hello" }, 201))
.get("api/book", (c) => c.json({ key: "123", title: "Hello" }, 200));
} // main.ts
import { Hono } from "hono";
import { hc } from "hono/client";
import { addBookRoutes } from "./books";
import { addMovieRoutes } from "./movies";
const app = new Hono();
addBookRoutes(app);
addMovieRoutes(app);
type App = ReturnType<typeof addInvoiceRoutes> & ReturnType<typeof addMovieRoutes>;
const client = hc<typeof routes>("http://localhost:5173");
client.api.book // this is now working!
This has always been a goal for me; having a long list of urls but having the handler in some other place to make the list more readable ("RoR-like Controller" as it been called in the docs). I created a few helper types and got it working: import { Context, Hono, MiddlewareHandler } from "hono";
/**
* Helper types
*/
type Client<T> = T extends Hono<any, infer S, any> ? S : never;
type ExtraxtInput<I> = I extends MiddlewareHandler<any, any, infer S> ? S : never;
type ExtractRoutes = keyof Client<typeof routes>;
type Ctx<P extends ExtractRoutes, V extends MiddlewareHandler<any, any, any> = never> = Context<any, P, ExtraxtInput<V>>;
/**
* Handler
*/
const bodySchema = zValidator(
"json",
z.object({ name: z.string() })
);
function myHandler(c: Ctx<"/book/:key", typeof bodySchema>) {
const key = c.req.param().key // typed
const name = c.req.valid("json").name // typed
return c.json({ name, key });
}
/**
* Routes
*/
const routes = app.post("/book/:key", bodySchema, myHandler);
/**
* RPC
*/
export const client = hc<typeof routes>("http://localhost:5173");
const t = client.book[":key"]
.$post({ param: { key: "123" }, json: { name: "GoT" } })
.then((res) => res.json()); // all typed For now am I happy with alternative 2 (I have not added Env but that should be easy to add if needed). |
Beta Was this translation helpful? Give feedback.
-
Hi @oskarkivra
// books.ts
import { Hono } from 'hono'
const books = new Hono().get('/', (c) => c.json({ message: 'books' }))
export default books // index.ts
import { Hono } from 'hono'
import { hc } from 'hono/client'
import books from './books'
const root = new Hono().get('/', (c) => c.json({ message: 'hi' }))
const app = new Hono()
const routes = app.route('/', root).route('/api/book', books)
const client = hc<typeof routes>('http://localhost:5173') |
Beta Was this translation helpful? Give feedback.
That's a bummer.
If someone else are looking for alternatives I can share my findings: