Hmza
Hmza•4mo ago

convex x hono

i'm not able to make the hono .notfound endpoint work. i get errors if i just visit a wrong path rather it showing a message of not found or something.
import { Hono } from "hono";
import { HonoWithConvex, HttpRouterWithHono } from "convex-helpers/server/hono";
import { ActionCtx } from "./_generated/server";
import { internal } from "./_generated/api";
import { z } from "zod";

const app: HonoWithConvex<ActionCtx> = new Hono();

const mySchema = z.object({
number: z.string().min(1),
cursor: z.string().optional(),
numItems: z.number().int().min(1).max(100).default(10),
});

app.get("/", (c) => c.json({ message: "Welcome to the cool stuff!" }));

app.get("/number/:number", async (c) => {
try {
const params = mySchema.parse({
//my params
});

const data = await c.env.runQuery(my internalquery with param and pagination);

if (data === null) {
return c.json({ error: " not found" }, 404);
}

return c.json({
status: "success",
data: data.items,
pagination: {
hasMore: data.paginationInfo.hasMore,
nextCursor: data.paginationInfo.continueCursor,
},
metadata: {
//metadata
},
}, 200);
} catch (error) {
console.error("Error processing:", error);
if (error instanceof z.ZodError) {
return c.json({ status: "error", error: "Invalid input", details: error }, 400);
}
return c.json({ status: "error", error: "Internal server error" }, 500);
}
});

app.notFound((c) => c.json({ status: "error", error: "Not found" }, 404));

export default new HttpRouterWithHono(app);
import { Hono } from "hono";
import { HonoWithConvex, HttpRouterWithHono } from "convex-helpers/server/hono";
import { ActionCtx } from "./_generated/server";
import { internal } from "./_generated/api";
import { z } from "zod";

const app: HonoWithConvex<ActionCtx> = new Hono();

const mySchema = z.object({
number: z.string().min(1),
cursor: z.string().optional(),
numItems: z.number().int().min(1).max(100).default(10),
});

app.get("/", (c) => c.json({ message: "Welcome to the cool stuff!" }));

app.get("/number/:number", async (c) => {
try {
const params = mySchema.parse({
//my params
});

const data = await c.env.runQuery(my internalquery with param and pagination);

if (data === null) {
return c.json({ error: " not found" }, 404);
}

return c.json({
status: "success",
data: data.items,
pagination: {
hasMore: data.paginationInfo.hasMore,
nextCursor: data.paginationInfo.continueCursor,
},
metadata: {
//metadata
},
}, 200);
} catch (error) {
console.error("Error processing:", error);
if (error instanceof z.ZodError) {
return c.json({ status: "error", error: "Invalid input", details: error }, 400);
}
return c.json({ status: "error", error: "Internal server error" }, 500);
}
});

app.notFound((c) => c.json({ status: "error", error: "Not found" }, 404));

export default new HttpRouterWithHono(app);
12 Replies
ballingt
ballingt•4mo ago
@Hmza what is .notfound, how is it supposed to work? Is it a 404 sort of thing? If that's not wired up, maybe it's something to update in https://github.com/get-convex/convex-helpers/blob/main/packages/convex-helpers/README.md#hono-for-advanced-http-endpoint-definitions
v
v•4mo ago
Yeah this has been a bug for a while now, I forgot to report. Probably easy to fix, likely with HttpRouterWithHono this fixed it
override lookup = (path: string, method: RoutableMethod | "HEAD") => {
// const match = this._app.router.match(method, path);
// if (match === null) {
// return [this._handler, normalizeMethod(method), path] as const;
// }
// // There might be multiple handlers for a route (in the case of middleware),
// // so choose the most specific one for the purposes of logging
// const handlersAndRoutes = match[0];
// const mostSpecificHandler =
// handlersAndRoutes[handlersAndRoutes.length - 1]![0][0];
// // On the first request let's populate a lookup from handler to info
// if (this._handlerInfoCache.size === 0) {
// for (const r of this._app.routes) {
// this._handlerInfoCache.set(r.handler, {
// method: normalizeMethod(method),
// path: r.path,
// });
// }
// }
// const info = this._handlerInfoCache.get(mostSpecificHandler);
// if (info) {
// return [this._handler, info.method, info.path] as const;
// }

return [this._handler, normalizeMethod(method), path] as const;
};
override lookup = (path: string, method: RoutableMethod | "HEAD") => {
// const match = this._app.router.match(method, path);
// if (match === null) {
// return [this._handler, normalizeMethod(method), path] as const;
// }
// // There might be multiple handlers for a route (in the case of middleware),
// // so choose the most specific one for the purposes of logging
// const handlersAndRoutes = match[0];
// const mostSpecificHandler =
// handlersAndRoutes[handlersAndRoutes.length - 1]![0][0];
// // On the first request let's populate a lookup from handler to info
// if (this._handlerInfoCache.size === 0) {
// for (const r of this._app.routes) {
// this._handlerInfoCache.set(r.handler, {
// method: normalizeMethod(method),
// path: r.path,
// });
// }
// }
// const info = this._handlerInfoCache.get(mostSpecificHandler);
// if (info) {
// return [this._handler, info.method, info.path] as const;
// }

return [this._handler, normalizeMethod(method), path] as const;
};
so ye
Hmza
HmzaOP•4mo ago
@ballingt just meant that if you visit a route that is not in scope (you didn't created it) then it gives all kind of errors rather running the 404 route. i think @v suggest something good. can we publish this if works? thanks
v
v•4mo ago
thats just temporary a temporary fix. the logs wont have the actual route just the path. for example the logs should show this
No description
v
v•4mo ago
but with that code they will show
No description
v
v•4mo ago
i think this code would do better
override lookup = (path: string, method: RoutableMethod | "HEAD") => {
const match = this._app.router.match(method, path);
if (match === null) {
return [this._handler, normalizeMethod(method), path] as const;
}
// There might be multiple handlers for a route (in the case of middleware),
// so choose the most specific one for the purposes of logging

const handlersAndRoutes = match[0];

if (!handlersAndRoutes || handlersAndRoutes.length === 0) {
return [this._handler, normalizeMethod(method), path] as const;
}

const mostSpecificHandler =
handlersAndRoutes[handlersAndRoutes.length - 1]![0][0];
// On the first request let's populate a lookup from handler to info
if (this._handlerInfoCache.size === 0) {
for (const r of this._app.routes) {
this._handlerInfoCache.set(r.handler, {
method: normalizeMethod(method),
path: r.path,
});
}
}
const info = this._handlerInfoCache.get(mostSpecificHandler);
if (info) {
return [this._handler, info.method, info.path] as const;
}

return [this._handler, normalizeMethod(method), path] as const;
};
}
override lookup = (path: string, method: RoutableMethod | "HEAD") => {
const match = this._app.router.match(method, path);
if (match === null) {
return [this._handler, normalizeMethod(method), path] as const;
}
// There might be multiple handlers for a route (in the case of middleware),
// so choose the most specific one for the purposes of logging

const handlersAndRoutes = match[0];

if (!handlersAndRoutes || handlersAndRoutes.length === 0) {
return [this._handler, normalizeMethod(method), path] as const;
}

const mostSpecificHandler =
handlersAndRoutes[handlersAndRoutes.length - 1]![0][0];
// On the first request let's populate a lookup from handler to info
if (this._handlerInfoCache.size === 0) {
for (const r of this._app.routes) {
this._handlerInfoCache.set(r.handler, {
method: normalizeMethod(method),
path: r.path,
});
}
}
const info = this._handlerInfoCache.get(mostSpecificHandler);
if (info) {
return [this._handler, info.method, info.path] as const;
}

return [this._handler, normalizeMethod(method), path] as const;
};
}
basically handlersAndRoutes.length === 0 i tested and it seems to fix it while the logs are as they were
ballingt
ballingt•4mo ago
sweet, wanna submit that as a PR? https://github.com/get-convex/convex-helpers
GitHub
GitHub - get-convex/convex-helpers: A collection of useful code to ...
A collection of useful code to complement the official packages. - get-convex/convex-helpers
v
v•4mo ago
done pr has been merged imagine it didnt fix it xd im kidding
jamalsoueidan
jamalsoueidan•4mo ago
you didnt write test for your fix?
v
v•4mo ago
it was 3 lines i just tested it myself lol
jamalsoueidan
jamalsoueidan•4mo ago
so you didnt write test and your pr gets merged, was this part of contex base code? 👀
v
v•4mo ago
GitHub
Refactor HttpRouterWithHono to handle empty handlersAndRoutes array...
…#262) Implements a fix allowing the Hono 404 route to trigger, preventing an error from being returned. discord

Did you find this page helpful?