Hono
Hono Recipe
Section titled “Hono Recipe”Hono is fetch-native, so it mounts UQL’s HTTP transport core directly. createFetchHandler returns a web-standard (request: Request) => Promise<Response>, and .mount() binds it to a prefix and strips that prefix before the handler sees the request. There is nothing to install beyond uql-orm.
import { Hono } from 'hono';import { createFetchHandler } from 'uql-orm/http';import './uql.config.js'; // setQuerierPool + entity importsimport { User, Post } from './shared/models/index.js';
const handler = createFetchHandler({ include: [User, Post] });
const app = new Hono();app.mount('/api', handler);
export default app; // Bun.serve, Deno.serve, Cloudflare Workers, Node via @hono/node-serverThis mounts the full wire protocol for each entity (list, get, count, create, upsert, bulk operations, delete) plus the QUERY transport. Because .mount() forwards every method to the handler, the QUERY method works here without extra routing.
Composing with Hono routes and middleware
Section titled “Composing with Hono routes and middleware”.mount() only claims the /api prefix, so your own Hono routes and middleware live side by side with the generated CRUD. Keep hand-written routes for read-modify-write logic, multi-entity transactions, aggregations, file uploads, and streaming:
import { cors } from 'hono/cors';
const app = new Hono();app.use('*', cors());app.get('/health', (c) => c.text('ok'));app.post('/checkout', (c) => c.json(runCheckout(c.req))); // custom business logicapp.mount('/api', handler); // entity CRUD under /apicreateFetchHandler accepts the core’s pre, preSave, preFilter, and post hooks. The hook context is the web Request, so read auth and tenant state from its headers:
const handler = createFetchHandler({ include: [User, Post], async preFilter({ query, context }) { // context is the web Request; abort by throwing with a numeric status const user = await authenticate(context.headers.get('authorization')); if (!user) { throw Object.assign(new Error('unauthorized'), { status: 401 }); } query.$where ??= {}; Object.assign(query.$where, { creatorId: user.id }); },});