Provider Resolution
Source: src/engine/type-resolver.ts
What
Extracts dependency information from all @Injectable() classes — their constructor dependencies, public method count, and file location.
Why
Rules like no-unused-providers, no-missing-injectable, and no-business-logic-in-controllers need to know which providers exist, what they depend on, and how many methods they expose.
Input
project: Project // ts-morph AST project
files: string[] // file paths to scan
Output
Map<string, ProviderInfo>
interface ProviderInfo {
name: string // class name
filePath: string
classDeclaration: ClassDeclaration
dependencies: string[] // constructor parameter type names
publicMethodCount: number
}
How It Works
For each file, finds all classes decorated with @Injectable():
- Extract constructor parameters — each parameter's type becomes a dependency name
- Normalize type names using
extractSimpleTypeName():import("@prisma/client").PrismaService→PrismaServiceRepository<User>→RepositoryConfigService→ConfigService
- Count public methods — methods with no access modifier or explicit
public
Example
Given this class:
@Injectable()
export class UserService {
constructor(
private readonly prisma: PrismaService,
private readonly config: ConfigService,
) {}
async findAll() { /* ... */ }
async findById(id: string) { /* ... */ }
private validate(user: User) { /* ... */ }
}
The resolver produces:
{
name: "UserService",
filePath: "/src/user/user.service.ts",
dependencies: ["PrismaService", "ConfigService"],
publicMethodCount: 2, // findAll + findById (validate is private)
}
Debugging Tips
- Only classes with
@Injectable()are resolved. Controllers (which use@Controller()) are not included in the providers map — they are handled separately during rule execution. - If a dependency name looks wrong (e.g., includes import paths), check the type annotation on the constructor parameter.