Context
Every procedure handler receives a ctx object with the current request, database client, authenticated user, and any state your plugins add. Each request gets its own isolated scope, extensible through TypeScript declaration merging.
Default Context
Section titled “Default Context”Every handler receives:
.query(async ({ input, ctx }) => { ctx.request // Fastify request ctx.reply // Fastify reply ctx.db // Prisma client (with ORM plugin) ctx.user // Authenticated user (with auth plugin)})Extending Context
Section titled “Extending Context”Use TypeScript declaration merging:
declare module '@veloxts/core' { interface BaseContext { tenant: Tenant; logger: Logger; }}Then populate in a plugin or middleware:
app.addHook('onRequest', async (request, reply) => { request.context = { ...request.context, tenant: await getTenant(request), logger: createLogger(request), };});Context in Guards
Section titled “Context in Guards”Guards receive the full context:
const isTenantAdmin = defineGuard({ name: 'isTenantAdmin', check: (ctx) => ctx.user?.role === 'admin' && ctx.tenant?.id === ctx.user?.tenantId, message: 'Must be tenant admin',});