Quick Start
Get started with hypequery.
What you'll build
In this guide you will:
- build a typed ClickHouse query with
db.table(...) - wrap that query with object-style
query({ ... })when it becomes reusable - run it locally with
query.execute() - expose the same query over HTTP with
serve({ queries })
This is the main recommended path for new projects.
Install the packages
npm install @hypequery/clickhouse @hypequery/serve zod
npm install -D @hypequery/clipnpm add @hypequery/clickhouse @hypequery/serve zod
pnpm add -D @hypequery/cliyarn add @hypequery/clickhouse @hypequery/serve zod
yarn add -D @hypequery/clibun add @hypequery/clickhouse @hypequery/serve zod
bun add -D @hypequery/cliScaffold the analytics folder
Run:
npx hypequery initThe CLI will create a structure like:
schema.ts
client.ts
queries.ts
.env
Build the query, then wrap it
Open analytics/queries.ts. First build the query with the typed builder, then wrap it with query({ ... }) so it becomes a reusable definition:
import { initServe } from '@hypequery/serve';
import { z } from 'zod';
import { db } from './client';
const { query, serve } = initServe({
context: () => ({ db }),
basePath: '/api/analytics',
});
const activeUsersQuery = ({ limit }: { limit: number }) =>
db
.table('users')
.select(['id', 'email', 'created_at'])
.where('status', 'eq', 'active')
.orderBy('created_at', 'DESC')
.limit(limit)
.execute();
const activeUsers = query({
description: 'Most recent active users',
input: z.object({
limit: z.number().min(1).max(500).default(50),
}),
output: z.array(z.object({
id: z.string(),
email: z.string(),
created_at: z.string(),
})),
query: async ({ ctx, input }) => {
return activeUsersQuery({ limit: input.limit });
},
});
export const api = serve({
queries: { activeUsers },
});
api.route('/active-users', api.queries.activeUsers, { method: 'POST' });The important distinction:
activeUsersQuery(...)is plain typed query-builder logicactiveUsers = query({ ... })turns that logic into a named reusable contractserve({ queries: { activeUsers } })exposes that contract through a runtime
Run the query locally
Because activeUsers is executable, you can call it without HTTP:
const latest = await activeUsers.execute({
input: { limit: 25 },
});
console.log(latest);You can also execute through the exported API:
const latest = await api.run('activeUsers', {
input: { limit: 25 },
});Preview docs and routes
Start the dev server:
npx hypequery dev analytics/queries.tsWith basePath: '/api/analytics', the runtime exposes:
- docs at
http://localhost:4000/api/analytics/docs - OpenAPI at
http://localhost:4000/api/analytics/openapi.json - your route at
http://localhost:4000/api/analytics/active-users
Try it:
curl -X POST http://localhost:4000/api/analytics/active-users \
-H "Content-Type: application/json" \
-d '{"limit": 10}'What to learn next
- Read Re-using Queries for the distinction between builder queries and
query({ ... }) - Read Core Concepts for the full builder, query, and serve model
- See Next.js, Vite, or Node.js for framework setup