Skip to main content
rule

nestjs-anti-hallucination-cursorrules-prompt-file — Cursor rule

Cursor rule that stops AI models from generating fake NestJS imports, legacy TypeORM calls, and untyped code.

Install into Cursor · Manually: put the files in place All methods and platforms ↓
.cursor/rules/nestjs-anti-hallucination-cursorrules-prompt-file.mdc
Open on GitHub

What nestjs-anti-hallucination-cursorrules-prompt-file does

This rule guides Cursor assistants working on NestJS backends by blocking common generative errors. It explicitly bans phantom package paths such as @nestjs/core/decorators or subpath imports for Swagger, forcing direct imports. Legacy libraries like nestjs-redis or the old Bull package get rejected in favor of @nestjs-modules/ioredis and @nestjs/bullmq with WorkerHost.

Code quality instructions also enforce strict typing and framework conventions. The assistant cannot emit any, must replace direct getRepository() calls with constructor injection via @InjectRepository, and must avoid Express response objects in standard handlers. Database migrations cannot include DROP TABLE, and queries must use parameterized placeholders.

Because setting up DTO decorators without pipeline configuration leads to silent validation bugs, the instructions demand registering ValidationPipe in main.ts with explicit transform flags.

What it helps with

  • Block phantom import paths across NestJS and TypeORM modules
  • Migrate background job code from legacy @nestjs/bull to @nestjs/bullmq
  • Enforce unknown instead of any in TypeScript error handling
  • Prevent unparameterized SQL queries and production database synchronization

Example prompts for the agent

  • Create an async TypeORM database module using ConfigService
  • Implement a BullMQ queue processor for user registration emails
  • Build a controller endpoint with DTO validation and swagger annotations

How to install nestjs-anti-hallucination-cursorrules-prompt-file

Manually: put the files in place

.cursor/rules/nestjs-anti-hallucination-cursorrules-prompt-file.mdc

Frontmatter: description, globs, alwaysApply

Step by step, with commands for each platform: Cursor rules: .mdc files, four modes and what replaced .cursorrules

Questions about nestjs-anti-hallucination-cursorrules-prompt-file

How to install nestjs-anti-hallucination-cursorrules-prompt-file in Cursor?

Add the rule instructions to .cursor/rules/nestjs-anti-hallucination-cursorrules-prompt-file.mdc inside your repository.

What does nestjs-anti-hallucination-cursorrules-prompt-file do?

It overrides default generation behavior in Cursor to forbid deprecated APIs, fake export paths, and unsafe patterns in NestJS projects.

Why does the rule ban @nestjs/bull?

Bull is treated as legacy, so the instructions force the agent to write processors using @nestjs/bullmq and the WorkerHost class.

Source text

nestjs-anti-hallucination-cursorrules-prompt-file.mdc · CC0-1.0
---
description: "Cursor rules that block deprecated, phantom, or incorrect NestJS imports, decorators, providers, modules, and testing patterns."
globs: **/*
alwaysApply: false
---
# NestJS Anti-Hallucination Rules

These rules OVERRIDE all other generation behavior. Check EVERY line of generated code against these rules.

## Banned Imports & Phantom Packages

### NEVER import these — they don't exist or are deprecated:
```
❌ @nestjs/core/decorators    — not a real export path
❌ @nestjs/swagger/decorators — import from @nestjs/swagger directly
❌ @nestjs/typeorm/repository — not a real export path
❌ @nestjs/passport/strategies — import from passport-jwt, passport-local, etc.
❌ @nestjs/bull/decorators     — import from @nestjs/bullmq (bull is legacy)
❌ nestjs-redis               — use @nestjs-modules/ioredis or ioredis directly
❌ @nestjs/cqrs/decorators    — import from @nestjs/cqrs directly
❌ nestjs-config              — use @nestjs/config (official)
❌ nestjs-pino/logger          — import from nestjs-pino directly
```

### Correct import paths:
```typescript
// ✅ Swagger
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';

// ✅ TypeORM
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';

// ✅ BullMQ (NOT Bull)
import { InjectQueue, Processor, WorkerHost } from '@nestjs/bullmq';

// ✅ Config
import { ConfigService, ConfigModule } from '@nestjs/config';

// ✅ Passport
import { AuthGuard } from '@nestjs/passport';
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt';

// ✅ CQRS
import { CommandHandler, ICommandHandler, EventBus } from '@nestjs/cqrs';
```

## Deprecated Patterns — NEVER Generate These

### 1. getRepository() outside providers
```typescript
// ❌ DEPRECATED — removed in TypeORM 0.3+
const repo = getRepository(User);
const user = await getConnection().getRepository(User).find();

// ✅ CORRECT — inject via constructor
constructor(
  @InjectRepository(User)
  private readonly userRepo: Repository<User>,
) {}
```

### 2. @nestjs/bull (use @nestjs/bullmq)
```typescript
// ❌ OLD — @nestjs/bull with @Process decorator
import { Process, Processor } from '@nestjs/bull';
@Processor('queue')
class MyProcessor {
  @Process() async handle(job: Job) {}
}

// ✅ CURRENT — @nestjs/bullmq with WorkerHost
import { Processor, WorkerHost } from '@nestjs/bullmq';
@Processor('queue')
class MyProcessor extends WorkerHost {
  async process(job: Job): Promise<void> {}
}
```

### 3. Express-specific middleware mistakes
```typescript
// ❌ WRONG — Express req/res types in NestJS
import { Request, Response } from 'express';
@Get()
async findAll(@Req() req: Request, @Res() res: Response) {
  res.json(data); // Bypasses interceptors, serialization, exception filters
}

// ✅ CORRECT — Use NestJS decorators, return values
@Get()
async findAll(@Query() query: FindAllQueryDto): Promise<UserResponseDto[]> {
  return this.usersService.findAll(query);
}

// Only use @Res() when streaming files or SSE — add { passthrough: true }
@Get('download')
async download(@Res({ passthrough: true }) res: Response) {
  res.set('Content-Type', 'application/octet-stream');
  return new StreamableFile(stream);
}
```

### 4. Wrong decorator combinations
```typescript
// ❌ WRONG — @Injectable() on a controller
@Injectable()
@Controller('users')
export class UsersController {}

// ❌ WRONG — @Controller() on a service
@Controller()
@Injectable()
export class UsersService {}

// ❌ WRONG — @Body() in a GET handler
@Get()
async findAll(@Body() body: any) {} // GET requests should not have a body

// ❌ WRONG — Both @Param and @Query with same name
@Get(':id')
async findOne(@Param('id') paramId: string, @Query('id') queryId: string) {}
```

### 5. class-validator / class-transformer mistakes
```typescript
// ❌ WRONG — Validation without enabling in main.ts
// (AI often forgets this critical line)
// main.ts MUST have:
app.useGlobalPipes(new ValidationPipe({
  whitelist: true,            // Strip unknown properties
  forbidNonWhitelisted: true, // Throw on unknown properties
  transform: true,            // Auto-transform payloads to DTO instances
  transformOptions: {
    enableImplicitConversion: true,
  },
}));

// ❌ WRONG — Mixing validation decorators with wrong transform
export class CreateUserDto {
  @IsString()
  name: string;

  @IsNumber()
  age: string; // Type mismatch! Decorator says number, type says string
}

// ✅ CORRECT — Types match decorators
export class CreateUserDto {
  @IsString()
  @IsNotEmpty()
  name: string;

  @IsInt()
  @Min(0)
  age: number;
}
```

### 6. Async module pitfalls
```typescript
// ❌ WRONG — useFactory without async when awaiting
TypeOrmModule.forRootAsync({
  useFactory: (config: ConfigService) => ({
    type: 'postgres',
    url: config.get('DATABASE_URL'), // Not awaited, no inject
  }),
})

// ✅ CORRECT
TypeOrmModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: async (config: ConfigService) => ({
    type: 'postgres',
    url: config.getOrThrow<string>('DATABASE_URL'),
    autoLoadEntities: true,
    synchronize: false, // NEVER true in production
  }),
})
```

## Type Safety Rules

### NEVER generate `any`
```typescript
// ❌ BANNED
catch (error: any) { ... }
const data: any = await response.json();
private cache = new Map<string, any>();

// ✅ REQUIRED
catch (error: unknown) {
  if (error instanceof DomainError) { ... }
  throw error;
}
const data = await response.json() as PaymentGatewayResponse;
private cache = new Map<string, CachedSession>();
```

### NEVER generate untyped event payloads
```typescript
// ❌ WRONG
eventBus.emit('order.created', { order });

// ✅ CORRECT — Typed events
export class OrderCreatedEvent {
  constructor(
    public readonly orderId: string,
    public readonly userId: string,
    public readonly totalAmount: number,
    public readonly occurredAt: Date = new Date(),
  ) {}
}
eventBus.emit(new OrderCreatedEvent(order.id, order.userId, order.total));
```

## Configuration Safety

### NEVER generate hardcoded values for:
- Database connection strings
- API keys or secrets
- Port numbers
- Feature flags
- External service URLs

### ALWAYS use ConfigService with getOrThrow:
```typescript
// ❌ WRONG
const port = process.env.PORT || 3000;
const dbUrl = process.env.DATABASE_URL;

// ✅ CORRECT
const port = this.configService.getOrThrow<number>('app.port');
const dbUrl = this.configService.getOrThrow<string>('database.url');
```

## Database Safety

### NEVER generate:
```typescript
// ❌ synchronize: true in production config
// ❌ DROP TABLE or TRUNCATE in migration files
// ❌ Raw SQL without parameterized queries
await this.dataSource.query(`SELECT * FROM users WHERE id = '${userId}'`); // SQL injection!

// ✅ CORRECT
await this.dataSource.query(`SELECT * FROM users WHERE id = $1`, [userId]);
```

## Remember
- If you're unsure whether a package exists, DO NOT import it. Ask or check.
- If you're generating a NestJS pattern you haven't seen in the official docs, STOP and reconsider.
- When in doubt, generate LESS code with correct patterns rather than MORE code with guesses.

© PatrickJS · CC0-1.0 · PatrickJS/awesome-cursorrules

Similar IDE rules

All IDE rules for Backend and APIs →

From the same set210

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor