> hypequery

HTTP + OpenAPI

Expose hypequery metrics through HTTP handlers and autogenerated docs

HTTP + OpenAPI Delivery

We've simplified the serve API in v0.2. If you're looking for the older builder-first API, see Migrate from v0.1.x Serve API and v0.1.x Serve API.

hypequery can expose your queries as HTTP endpoints with automatically generated OpenAPI documentation.

Quick Example

Here's a complete example of exposing a query via HTTP:

1. Define your query:

// src/analytics/queries.ts
import { initServe } from '@hypequery/serve';
import { z } from 'zod';
import { db } from './client';

const { query, serve } = initServe({
  context: () => ({ db }),
});

const revenue = query({
  description: 'Get total revenue',
  output: z.object({
    total: z.number(),
    count: z.number(),
  }),
  query: async ({ ctx }) => {
    const rows = await ctx.db
      .table('orders')
      .sum('amount', 'total')
      .count('order_id', 'count')
      .execute();

    return rows[0];
  },
});

export const api = serve({
  queries: { revenue },
});

// ✅ Register the route - required for HTTP access!
api.route('/revenue', api.queries.revenue, { method: 'POST' });

2. Start the server:

npx hypequery dev src/analytics/queries.ts
# Server running at http://localhost:4000

hypequery dev spins up the same HTTP server your api.handler uses, so once you register routes (step 1) every endpoint is reachable without any extra wiring. In production you can do the equivalent by calling await api.start({ port }), or by embedding api.handler inside your own framework/server if you don't want to rely on the CLI entry point.

3. Call your API:

curl -X POST http://localhost:4000/revenue
# {"total": 125000, "count": 450}

That's it! Your query is now available as an HTTP endpoint with auto-generated OpenAPI docs at http://localhost:4000/docs.

Deployment Models

Integrate hypequery directly into your web framework. Routes run on the same port as your application.

Supported frameworks:

  • Next.js (Vercel adapter)
  • Express
  • Hono
  • Any framework with standard Request/Response handlers

Example: Next.js

// app/api/hypequery/[...hq]/route.ts
import { api } from '@/analytics/queries';
import { createFetchHandler } from '@hypequery/serve';

export const runtime = 'nodejs';

const handler = createFetchHandler(api.handler);

export const GET = handler;
export const POST = handler;
export const OPTIONS = handler;

Example: Express

Use the Node adapter to mount hypequery alongside your existing routes:

// server.ts
import express from 'express';
import { createNodeHandler } from '@hypequery/serve';
import { api } from './analytics/queries';

const app = express();

// Mount hypequery at /api/analytics
app.use('/api/analytics', createNodeHandler(api.handler));

app.listen(3000);

Standalone Server

Run a dedicated hypequery server on its own port:

// src/analytics/server.ts
import { api } from './queries';

await api.start({ port: 4000 });

api.start() starts the default Node server and returns a { stop() } handle for shutdown. If you need custom app routes, mount api.handler inside your own Express, Hono, or Next.js server instead of expecting an app object from start().

Or use the CLI:

# Development
npx hypequery dev src/analytics/queries.ts --port 4000

# Production
npx hypequery serve src/analytics/queries.ts --port 8080

Edge/Fetch Runtimes

Deploy to edge platforms using the standard Fetch API:

// Cloudflare Worker
import { api } from './analytics/queries';
import { createFetchHandler } from '@hypequery/serve';

const handler = createFetchHandler(api.handler);

export default {
  fetch(request: Request) {
    return handler(request);
  },
};

// Vercel Edge Function
import { api } from './analytics/queries';
import { createFetchHandler } from '@hypequery/serve';

const handler = createFetchHandler(api.handler);

export default function handler(request: Request) {
  return handler(request);
}

OpenAPI Documentation

Auto-generated OpenAPI specs are available at /openapi.json:

curl http://localhost:4000/openapi.json

Customize the generated OpenAPI document through serve({ openapi: ... }):

const api = serve({
  queries: { revenue },
  openapi: {
    title: 'My Analytics API',
    version: '2.0.0',
    servers: [
      { url: 'https://api.example.com', description: 'Production' },
    ],
  },
});

Documentation UI

Serve interactive API documentation from the built-in /docs route, or customize the generated page with serve({ docs: ... }):

const api = serve({
  queries: { revenue },
  docs: {
    title: 'My API Docs',
    subtitle: 'Analytics runtime',
    darkMode: true,
  },
});

The runtime will expose that UI at /docs automatically once routes are registered.

If you want to host the docs HTML yourself, use the exported helper:

import { buildDocsHtml } from '@hypequery/serve';

app.get('/docs', (req, res) => {
  res.send(buildDocsHtml('/openapi.json', {
    title: 'My API Docs',
    subtitle: 'Analytics runtime',
    darkMode: true,
  }));
});

Custom Routes

Register individual queries with custom paths and methods:

import { api } from './analytics/queries';

// Register with custom path
api.route('/analytics/revenue', api.queries.revenue, { method: 'POST' });

// Register as GET
api.route('/health', api.queries.healthCheck, { method: 'GET' });

// Use query metadata from definition
api.route('/weekly', api.queries.weeklyRevenue);

On this page