feat: Expand fleet to 23 skills across all domains
New skills (14): - nestjs-best-practices: 40 priority-ranked rules (kadajett) - fastapi: Pydantic v2, async SQLAlchemy, JWT auth (jezweb) - architecture-patterns: Clean Architecture, Hexagonal, DDD (wshobson) - python-performance-optimization: Profiling and optimization (wshobson) - ai-sdk: Vercel AI SDK streaming and agent patterns (vercel) - create-agent: Modular agent architecture with OpenRouter (openrouterteam) - proactive-agent: WAL Protocol, compaction recovery, self-improvement (halthelobster) - brand-guidelines: Brand identity enforcement (anthropics) - ui-animation: Motion design with accessibility (mblode) - marketing-ideas: 139 ideas across 14 categories (coreyhaines31) - pricing-strategy: SaaS pricing and tier design (coreyhaines31) - programmatic-seo: SEO at scale with playbooks (coreyhaines31) - competitor-alternatives: Comparison page architecture (coreyhaines31) - referral-program: Referral and affiliate programs (coreyhaines31) README reorganized by domain: Code Quality, Frontend, Backend, Auth, AI/Agent Building, Marketing, Design, Meta. Mosaic Stack is not limited to coding — the Orchestrator serves coding, business, design, marketing, writing, logistics, and analysis. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
94
skills/nestjs-best-practices/rules/di-scope-awareness.md
Normal file
94
skills/nestjs-best-practices/rules/di-scope-awareness.md
Normal file
@@ -0,0 +1,94 @@
|
||||
---
|
||||
title: Understand Provider Scopes
|
||||
impact: CRITICAL
|
||||
impactDescription: Prevents data leaks and performance issues
|
||||
tags: dependency-injection, scopes, request-context
|
||||
---
|
||||
|
||||
## Understand Provider Scopes
|
||||
|
||||
NestJS has three provider scopes: DEFAULT (singleton), REQUEST (per-request instance), and TRANSIENT (new instance for each injection). Most providers should be singletons. Request-scoped providers have performance implications as they bubble up through the dependency tree. Understanding scopes prevents memory leaks and incorrect data sharing.
|
||||
|
||||
**Incorrect (wrong scope usage):**
|
||||
|
||||
```typescript
|
||||
// Request-scoped when not needed (performance hit)
|
||||
@Injectable({ scope: Scope.REQUEST })
|
||||
export class UsersService {
|
||||
// This creates a new instance for EVERY request
|
||||
// All dependencies also become request-scoped
|
||||
async findAll() {
|
||||
return this.userRepo.find();
|
||||
}
|
||||
}
|
||||
|
||||
// Singleton with mutable request state
|
||||
@Injectable() // Default: singleton
|
||||
export class RequestContextService {
|
||||
private userId: string; // DANGER: Shared across all requests!
|
||||
|
||||
setUser(userId: string) {
|
||||
this.userId = userId; // Overwrites for all concurrent requests
|
||||
}
|
||||
|
||||
getUser() {
|
||||
return this.userId; // Returns wrong user!
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Correct (appropriate scope for each use case):**
|
||||
|
||||
```typescript
|
||||
// Singleton for stateless services (default, most common)
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
constructor(private readonly userRepo: UserRepository) {}
|
||||
|
||||
async findById(id: string): Promise<User> {
|
||||
return this.userRepo.findOne({ where: { id } });
|
||||
}
|
||||
}
|
||||
|
||||
// Request-scoped ONLY when you need request context
|
||||
@Injectable({ scope: Scope.REQUEST })
|
||||
export class RequestContextService {
|
||||
private userId: string;
|
||||
|
||||
setUser(userId: string) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
getUser(): string {
|
||||
return this.userId;
|
||||
}
|
||||
}
|
||||
|
||||
// Better: Use NestJS built-in request context
|
||||
import { REQUEST } from '@nestjs/core';
|
||||
import { Request } from 'express';
|
||||
|
||||
@Injectable({ scope: Scope.REQUEST })
|
||||
export class AuditService {
|
||||
constructor(@Inject(REQUEST) private request: Request) {}
|
||||
|
||||
log(action: string) {
|
||||
console.log(`User ${this.request.user?.id} performed ${action}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Best: Use ClsModule for async context (no scope bubble-up)
|
||||
import { ClsService } from 'nestjs-cls';
|
||||
|
||||
@Injectable() // Stays singleton!
|
||||
export class AuditService {
|
||||
constructor(private cls: ClsService) {}
|
||||
|
||||
log(action: string) {
|
||||
const userId = this.cls.get('userId');
|
||||
console.log(`User ${userId} performed ${action}`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Reference: [NestJS Injection Scopes](https://docs.nestjs.com/fundamentals/injection-scopes)
|
||||
Reference in New Issue
Block a user