> Every UQL docs page, as Markdown: https://uql-orm.dev/llms.txt
> The same docs over MCP: https://uql-orm.dev/mcp
> Before writing UQL code, read the skill: https://uql-orm.dev/.well-known/agent-skills/uql-orm/SKILL.md

# NestJS

> Use UQL in NestJS with UqlModule, an injectable querier pool, request-scoped tenant context and optional CRUD routes.

Source: https://uql-orm.dev/nestjs

`uql-orm/nestjs` registers your querier pool with Nest’s dependency injection and ends it when the app shuts down. It supports Nest 10 to 12 and is tested against Nest 12.

## Setup

```ts title="app.module.ts"
import { Module } from '@nestjs/common';
import { UqlModule } from 'uql-orm/nestjs';
import { pool } from './uql.config.js';

@Module({
  imports: [UqlModule.forRoot({ pool })], // global unless you pass global: false
})
export class AppModule {}
```

To build the pool from other providers, use `forRootAsync`:

```ts
import { ConfigModule, ConfigService } from '@nestjs/config';

UqlModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) =>
    new PgQuerierPool({ connectionString: config.get('DATABASE_URL') }),
});
```

Call `app.enableShutdownHooks()` in `main.ts` so the pool ends on `SIGTERM`.

Declare your entities with [`defineEntity`](https://uql-orm.dev/entities/imperative.md) rather than decorators. Nest’s constructor injection needs `experimentalDecorators: true`, and one `tsconfig.json` cannot compile both decorator specs. `defineEntity` takes the same options, produces the same metadata and runs the same checks, except one foreign-key case.

CommonJS and ESM apps both work, since Node loads UQL’s ESM through `require(esm)`. Keep `module` at `commonjs` or `nodenext`, as Nest scaffolds it; `node16` and `node18` refuse the import.

## Injecting the pool

Inject the pool with the `UQL_QUERIER_POOL` token. Never make a `Querier` a provider: it holds a connection, which a singleton would pin.

```ts
import { Inject, Injectable } from '@nestjs/common';
import type { QuerierPool, Query, UniversalQuerier } from 'uql-orm';
import { UQL_QUERIER_POOL } from 'uql-orm/nestjs';
import { User } from './shared/models/index.js';

@Injectable()
export class UsersService {
  constructor(@Inject(UQL_QUERIER_POOL) private readonly pool: QuerierPool) {}

  findMany(q: Query<User>) {
    return this.pool.findMany(User, q);
  }

  create(user: User, db: UniversalQuerier = this.pool) {
    return db.insertOne(User, user);
  }
}
```

`create` accepts a [`UniversalQuerier`](https://uql-orm.dev/querying/querier.md#accept-a-universalquerier) that defaults to the pool. That lets a caller run several services in one transaction by passing its querier down:

```ts
signUp(user: User) {
  return this.pool.transaction(async (querier) => {
    await this.users.create(user, querier);
    await this.audit.record({ type: 'user.created' }, querier);
  });
}
```

In controllers, validate the few arguments an endpoint accepts and build the query on the server, rather than taking a client’s query. In Nest 12, `@Body({ schema })`, `@Query` and `@Param` take a Standard Schema such as zod, which `StandardSchemaValidationPipe` checks.

## Multi-tenancy

Pass `getContext` and the module adds a global interceptor that runs each request inside `withContext`. A `security` [filter](https://uql-orm.dev/multi-tenancy.md) then scopes every query in the request, relations, cascades and transactions included:

```ts
type AuthedRequest = { user: { id: string; tenantId: number } };

UqlModule.forRoot<AuthedRequest>({
  pool,
  getContext: (req) => ({ tenantId: req.user.tenantId, userId: req.user.id }),
});
```

Interceptors run after guards, so `req.user` is already set. The context reaches controllers and services but not guards or exception filters. If you need it earlier, say from a header, use your own middleware: `withContext(context, () => next())`.

## Auto-generated CRUD

Nest’s default platform is Express 5, so the [Express middleware](https://uql-orm.dev/express.md) mounts in `main.ts`:

```ts title="main.ts"
import { NestFactory } from '@nestjs/core';
import { querierMiddleware } from 'uql-orm/express';

const app = await NestFactory.create(AppModule);
app.enableShutdownHooks();
app.use('/api', querierMiddleware({ pool, include: [User, Post] }));
await app.listen(3000);
```

Unknown routes fall through to your controllers. On the Fastify platform, use the [`createRequestHandler` bridge](https://uql-orm.dev/fastify.md).
