Serve integration
Expose dataset definitions through the Serve runtime.
@hypequery/serve can expose semantic dataset endpoints from the same definitions you use with createDatasetClient.
Use Serve when dataset logic needs an HTTP boundary, OpenAPI/docs, auth, tenancy, caching, middleware, or React integration.
Register datasets
Pass a query builder plus the datasets you want to expose.
import { initServe } from '@hypequery/serve';
import { db } from './client.js';
import { Orders } from './datasets/orders.js';
const { query, serve } = initServe({
context: () => ({ db }),
});
export const api = serve({
queryBuilder: db,
datasets: { orders: Orders },
});Dataset endpoints validate dimensions, measures, filters, time grains, and ordering against the dataset definition. A limit above the endpoint's maxLimit is clamped to maxLimit rather than rejected.
Endpoint shapes
Semantic endpoints are generated as POST endpoints.
| Config | Endpoint shape | Use it for |
|---|---|---|
datasets: { orders: Orders } | /datasets/orders/query | Flexible same-dataset rollups |
The exact URL is prefixed by your Serve basePath.
Dataset endpoint input
{
"dimensions": ["country", "status"],
"measures": ["revenue", "orderCount"],
"filters": [
{ "field": "status", "operator": "eq", "value": "completed" }
],
"limit": 10
}Pagination
Dataset endpoints support offset pagination. Send limit and offset; the response reports the served offset and a hasMore flag so clients know whether another page exists.
{
"dimensions": ["country"],
"measures": ["revenue"],
"limit": 50,
"offset": 50
}In React, useInfiniteDataset handles offset/hasMore for you.
Include result metadata
Semantic endpoints return { data } by default. Include metadata with either includeMeta: true in the request body or the x-include-meta: true header.
{
"dimensions": ["country"],
"measures": ["revenue"],
"limit": 10,
"includeMeta": true
}Public metadata includes timing, row count, cache status, and pagination. SQL and internal tenant IDs are omitted by default.
For a trusted diagnostic endpoint, set trustedDiagnostics: true on the server-side entry and restrict it with authentication and roles:
datasets: {
orders: { dataset: Orders, trustedDiagnostics: true, requiredRoles: ['analytics-admin'] },
},Clients still request metadata with includeMeta or x-include-meta; those request flags cannot grant diagnostic access.
Query definitions plus datasets
You can expose hand-authored query definitions and generated semantic endpoints from the same API.
const activeOrders = query({
query: ({ ctx }) =>
ctx.db
.table('orders')
.where('status', 'eq', 'active')
.limit(10)
.execute(),
});
export const api = serve({
queryBuilder: db,
queries: { activeOrders },
datasets: { orders: Orders },
});Use hand-authored queries for bespoke application endpoints. Use datasets for governed analytics endpoints generated from semantic definitions.
Per-entry options
Datasets can be registered directly or with endpoint-specific options.
export const api = serve({
queryBuilder: db,
datasets: {
orders: {
dataset: Orders,
requiredRoles: ['analytics'],
cache: 60_000,
maxLimit: 100,
},
},
});For routing, auth, OpenAPI, and React hooks, see the Serve docs and React docs.
Logical discovery
GET /discovery returns a bounded logical catalog and authenticates by default.
Set discovery: { requiresAuth: false } only for intentionally public discovery;
configure roles/scopes through the same object. Customize the path with
semanticPaths.discovery.
The legacy public /contract retains its version and opaque definition
contentHash, but omits physical sources, columns, SQL, join keys and tenant
policy. Use local serializeSemanticContract for trusted snapshots and codegen
that need physical definitions.
The HTTP projection's contentHash identifies the original definition; it is
not a digest of the public response and cannot verify that response's JSON.