SQLCommenter for MikroORM
import { Tabs, TabItem } from “@astrojs/starlight/components”;
@query-doctor/sqlcommenter-mikroorm hooks into MikroORM’s built-in onQuery configuration — no monkey-patching required. Every SQL query carries a structured SQLCommenter comment with contextual metadata. Query Doctor reads these comments to connect queries back to the code and request that produced them.
Prerequisites
Section titled “Prerequisites”- Node.js >= 24.8.0
- MikroORM >= 6.4.0
- ESM project (
"type": "module"in yourpackage.json)
Installation
Section titled “Installation”Basic setup
Section titled “Basic setup”Call patchMikroORM on your MikroORM instance after initialization:
import { MikroORM } from "@mikro-orm/core";import { patchMikroORM } from "@query-doctor/sqlcommenter-mikroorm";
const mikroORM = await MikroORM.init({ dbName: "my-db", entities: [...],});const orm = patchMikroORM(mikroORM);Every query executed through orm now includes a SQL comment with:
| Tag | Included by default | Description |
|---|---|---|
db_driver | Yes | Identifies MikroORM as the driver |
file | Yes | Source file that triggered the query |
func_name | When named | Enclosing function/method — edit-stable, omitted if anonymous |
route | No | HTTP route (requires framework middleware) |
method | No | HTTP request method (requires framework middleware) |
| Trace context | Automatic | OpenTelemetry trace/span IDs when a tracer is active |
| Custom fields | No | Any arbitrary key/value metadata you provide |
Framework integration
Section titled “Framework integration”To capture route and method, use the withRequestContext function from the /http export. You can also pass any arbitrary key/value metadata.
Express
Section titled “Express”import { withRequestContext } from "@query-doctor/sqlcommenter-mikroorm/http";
app.use((req, res, next) => { withRequestContext({ route: req.route.path, method: req.method }, next);});import { withRequestContext } from "@query-doctor/sqlcommenter-mikroorm/http";import { routePath } from "hono/route";
app.use((c, next) => { withRequestContext({ route: routePath(c), method: c.req.method }, next);});Fastify
Section titled “Fastify”The simplest way is the first-party plugin, which registers a global onRequest hook covering the whole request lifecycle:
import { sqlcommenterFastify } from "@query-doctor/sqlcommenter-mikroorm/fastify";
// Register before any plugin whose hooks issue queries (e.g. auth).await app.register(sqlcommenterFastify);To wire it by hand instead, register the hook globally with fastify-plugin — a plain register() encapsulates the hook and it silently tags nothing:
import fp from "fastify-plugin";import { withRequestContext } from "@query-doctor/sqlcommenter-mikroorm/http";
const sqlcommenter = fp((app, _opts, done) => { app.addHook("onRequest", (request, _reply, next) => { // `routerPath` was removed in Fastify v5; `routeOptions.url` is the matched route pattern. withRequestContext( { route: request.routeOptions?.url ?? request.url, method: request.method, }, next, ); }); done();});
await app.register(sqlcommenter);NestJS
Section titled “NestJS”import { withRequestContext } from "@query-doctor/sqlcommenter-mikroorm/http";
@Injectable()export class SqlcommenterMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { withRequestContext({ route: req.path, method: req.method }, next); }}