Skip to content

Elysia

Elysia is fetch-native, so it mounts the HTTP transport core directly: .mount() binds the handler to a prefix and strips that prefix before it sees the request. Nothing to install beyond uql-orm.

import { cors } from '@elysiajs/cors';
import { Elysia } from 'elysia';
import { createFetchHandler } from 'uql-orm/http';
import './uql.config.js'; // setQuerierPool + entity imports
import { Post, User } from './shared/models/index.js';
const handler = createFetchHandler({ include: [User, Post] });
new Elysia()
.use(cors())
.get('/health', () => 'ok')
.post('/checkout', ({ body }) => runCheckout(body)) // custom business logic
.mount('/api', handler) // entity CRUD under /api
.listen(3000);

That serves the full wire protocol per entity. Because .mount() forwards every method, the QUERY transport works with no extra routing. .mount() claims only the /api prefix, so your own routes, plugins and lifecycle hooks sit beside the generated CRUD; keep them for read-modify-write logic, multi-entity transactions, aggregations, uploads and streaming. Unknown routes under the prefix return a 404 from the handler.

getContext receives the web Request and returns the ambient context for the whole request, so a security filter scopes every query it runs, non-bypassable from the wire and fail-closed:

const handler = createFetchHandler({
include: [User, Post],
async getContext(request) {
const user = await authenticate(request.headers.get('authorization'));
if (!user) {
throw Object.assign(new Error('unauthorized'), { status: 401 }); // numeric status becomes the HTTP status
}
return { tenantId: user.tenantId, userId: user.id };
},
});

The core’s hooks cover everything else: shaping a response, stamping a field, rejecting a payload.