Elysia
Elysia Recipe
Section titled “Elysia Recipe”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 importsimport { 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.
Authorization and tenant scoping
Section titled “Authorization and tenant scoping”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.