I ran nestjs-doctor on this repo — it catches NestJS-specific issues that ESLint can't.
94 / 100 ★★★★★ Excellent
1 error · 28 warnings · 9 info · 21/113 files · 243 ms
Score is high. Three things stood out:
1. new instead of letting NestJS handle it
// throttler.storage.ts
constructor(public redis: Redis) {
this.redisStorage = new ThrottlerStorageRedisService(redis);
}
This creates the instance manually, so NestJS doesn't know about it — no lifecycle hooks, no test overrides, no scoping.
Register it as a provider and inject it instead. Docs: Custom Providers
2. Health/metrics endpoints don't say they're public
// health.controller.ts
@Controller(HEALTH_ENDPOINT)
export class HealthController {
@Get('deps')
@HealthCheck()
deps(): Promise<HealthCheckResult> { ... }
}
No @UseGuards(), no @Public(). They work today because there's no global guard, but the day someone adds APP_GUARD these break silently — including the health check your load balancer hits.
Add @Public() to make the intent explicit. Docs: Authentication
3. Importing directly from another module's folder
// todos.controller.ts
import { AuthGuard } from '../../common/guards/auth.guard';
Four files do this. If that guard moves or gets renamed, all four break. NestJS modules encapsulate providers for a reason — export it from the module's barrel and import from there.
Docs: Modules
CI / Pre-commit
# .github/workflows/ci.yml — after lint
- run: npx nestjs-doctor@latest . --min-score 80 --verbose
# .husky/pre-commit
npx nestjs-doctor@latest . --min-score 80
Zero config, ~250ms.
I ran
nestjs-doctoron this repo — it catches NestJS-specific issues that ESLint can't.Score is high. Three things stood out:
1.
newinstead of letting NestJS handle itThis creates the instance manually, so NestJS doesn't know about it — no lifecycle hooks, no test overrides, no scoping.
Register it as a provider and inject it instead. Docs: Custom Providers
2. Health/metrics endpoints don't say they're public
No
@UseGuards(), no@Public(). They work today because there's no global guard, but the day someone addsAPP_GUARDthese break silently — including the health check your load balancer hits.Add
@Public()to make the intent explicit. Docs: Authentication3. Importing directly from another module's folder
Four files do this. If that guard moves or gets renamed, all four break. NestJS modules encapsulate providers for a reason — export it from the module's barrel and import from there.
Docs: Modules
CI / Pre-commit
Zero config, ~250ms.