Use Case
Internal product APIs with embedded analytics
Layer type-safe analytics into the backend you already run. Keep product routes stable while exposing analytics under an internal namespace.
Contract impact
Zero endpoint breakage
Execution model
In-process + routed
Migration style
Endpoint-by-endpoint
Keep route contracts stable
Existing API consumers keep working while analytics ships behind internal paths.
Use one query definition
Call analytics from handlers with api.run(...) and expose the same logic via HTTP.
Scale rollout safely
Start with one endpoint, validate outcomes, then expand into a broader internal API surface.
Implementation flow
Step 1
Mount internal routes
Add HypeQuery under a dedicated internal namespace beside current handlers.
Step 2
Compose in endpoints
Pull analytics into product responses directly from business endpoints.
Step 3
Reuse query logic
Keep one typed source of truth for both in-process and routed analytics execution.
Works with your existing routes
Your backend stays in control. Mount HypeQuery routes where you want them.
import { createFetchHandler } from '@hypequery/serve';const hypequeryHandler = createFetchHandler(api.handler);app.route('/api/products', products);app.all('/internal/hq/*', (c) => hypequeryHandler(c.req.raw));Compose analytics directly in business endpoints
Use api.run(...) from existing handlers whenever product responses need analytics context.
const productId = c.req.param('productId').toUpperCase();const analytics = await api.run('productOverview', { productId,});return c.json({ productId, analytics });Define once, reuse everywhere
The same query definitions can power internal HTTP routes and in-process calls.
const serve = initServe({ context: () => ({ db }),});export const api = serve.define({ basePath: '/internal/hq', queries: serve.queries({ topProducts: query .output(z.array(z.object({ product_id: z.string(), avg_order_value: z.number(), }))) .query(({ ctx }) => ctx.db .table('analytics.orders') .select(['payment_type as product_id']) .count('trip_id', 'orders') .avg('order_total', 'avg_order_value') .groupBy(['payment_type']) .execute() ), }),});Ready to implement
Use this as your first production migration path
- Keep existing consumer contracts intact
- Move analytics logic into typed definitions
- Expand exposure only when your team is ready