import { ClassDeclaration, Project, SourceFile } from "ts-morph"; //#region src/common/rule-scope.d.ts type RuleScope = "file" | "project" | "schema"; //#endregion //#region src/common/diagnostic.d.ts type Severity = "error" | "warning" | "info"; /** * Where a diagnostic is allowed to appear. A rule can be reported without * moving the score or failing a build. */ type DiagnosticSurface = "cli" | "prComment" | "score" | "ciFailure"; type Category = "security" | "performance" | "correctness" | "architecture" | "schema"; interface SourceLine { line: number; text: string; } interface BaseDiagnostic { category: Category; filePath: string; help: string; message: string; rule: string; scope?: RuleScope; severity: Severity; /** Absent means every surface. */ surfaces?: DiagnosticSurface[]; /** The emitting rule's `meta.tags`, when it declares any. */ tags?: string[]; } interface CodeDiagnostic extends BaseDiagnostic { column: number; line: number; sourceLines?: SourceLine[]; } interface SchemaDiagnostic extends BaseDiagnostic { entity: string; schemaColumn?: string; } type Diagnostic = CodeDiagnostic | SchemaDiagnostic; declare function isCodeDiagnostic(d: Diagnostic): d is CodeDiagnostic; declare function isSchemaDiagnostic(d: Diagnostic): d is SchemaDiagnostic; /** Absent surfaces mean the diagnostic appears everywhere. */ declare const onSurface: (diagnostic: BaseDiagnostic, surface: DiagnosticSurface) => boolean; /** The diagnostics a surface is allowed to show. */ declare const forSurface: (diagnostics: T[], surface: DiagnosticSurface) => T[]; //#endregion //#region src/common/endpoint.d.ts /** * Classifies a dependency's role in the NestJS application. */ type DependencyType = "service" | "repository" | "guard" | "interceptor" | "pipe" | "filter" | "gateway" | "step" | "throw" | "unknown"; interface StepStatement { assignedTo: string | null; text: string; } /** * Merged guard-throw info attached to a call node when the return value * is immediately null-checked and throws an exception. */ interface GuardThrow { branchKind: string | null; callSiteLine: number; className: string; conditionText: string | null; message: string | null; } /** * A per-method dependency node. Each method call becomes its own node * so that call order and conditionality are visible in the graph. */ interface MethodDependencyNode { /** Variable name the return value is assigned to (e.g. "existing" from `const existing = ...`) */ assignedTo: string | null; /** Shared ID for mutually exclusive branches from the same conditional (e.g., "L358") */ branchGroupId: string | null; /** Branch type: "if" | "else-if" | "else" | "case" | "default" | "catch" | "ternary-true" | "ternary-false" */ branchKind: string | null; /** Line where the call to this dependency is made in the parent method */ callSiteLine: number; className: string; /** Leading comment above the call site (e.g. "Verify pool belongs to organization") */ comment: string | null; conditional: boolean; /** Condition expression text (e.g., "!owner"), null if unconditional */ conditionText: string | null; dependencies: MethodDependencyNode[]; /** Last line of the method declaration (for full-function highlighting) */ endLine: number; /** Set when this class's subtree was already expanded at an earlier call site */ expandedElsewhere?: true; filePath: string; /** Merged guard-throw for call nodes (fetch + null-check + throw pattern) */ guardThrow: GuardThrow | null; /** Iteration context: "loop" | "callback" | "concurrent" | null */ iterationKind: "loop" | "callback" | "concurrent" | null; /** Short label for the construct: "map" | "forEach" | "for-of" | "all" | etc. */ iterationLabel: string | null; line: number; methodName: string | null; order: number; /** Method parameter names and types (from TS signature) */ parameters: MethodParameterInfo[]; /** Return type from TS method signature (unwrapped from Promise/Observable) */ returnType: string | null; /** Inline logic statements for step nodes (only populated when type === "step") */ stepStatements: StepStatement[]; /** Exception message for standalone throw nodes */ throwMessage: string | null; totalMethods: number; type: DependencyType; } interface MethodParameterInfo { name: string; type: string | null; } interface ApiBodyInfo { description: string | null; type: string | null; } interface ApiParamInfo { description: string | null; name: string; required: boolean; type: string | null; } interface ApiResponseInfo { description: string | null; status: number; type: string | null; } interface SwaggerMetadata { body: ApiBodyInfo | null; description: string | null; params: ApiParamInfo[]; queryParams: ApiParamInfo[]; responses: ApiResponseInfo[]; summary: string | null; } /** * Represents a single HTTP endpoint in a NestJS controller. * Contains a per-method dependency tree. */ interface EndpointNode { controllerClass: string; dependencies: MethodDependencyNode[]; /** Last line of the handler method (for full-function highlighting) */ endLine: number; filePath: string; handlerMethod: string; httpMethod: string; line: number; /** Return type from TS method signature (unwrapped from Promise/Observable) */ returnType: string | null; routePath: string; /** Swagger/OpenAPI metadata, null when no swagger decorators present */ swagger: SwaggerMetadata | null; /** Set when the trace hit MAX_DEPENDENCY_NODES, so `dependencies` is incomplete */ truncated?: true; } /** * Layer 2: method-level call trace node for deep dependency analysis. * Computed on demand via traceEndpointCalls(). */ interface MethodCallNode { calls: MethodCallNode[]; circular?: boolean; className: string; filePath: string; line: number; methodName: string; } /** * Complete endpoint dependency graph for a NestJS project. * JSON-safe — contains no Maps or AST references. */ interface EndpointGraph { endpoints: EndpointNode[]; } //#endregion //#region src/common/schema.d.ts interface SchemaColumn { defaultValue?: string; hasIndex?: boolean; isGenerated: boolean; isNullable: boolean; isPrimary: boolean; isUnique: boolean; name: string; type: string; } interface SchemaRelation { fromEntity: string; isNullable: boolean; onDelete?: string; propertyName: string; toEntity: string; type: "one-to-one" | "one-to-many" | "many-to-one" | "many-to-many"; } interface SchemaEntity { columns: SchemaColumn[]; filePath: string; indexes?: { columns: string[]; isUnique: boolean; }[]; name: string; relations: SchemaRelation[]; tableName: string; } /** * In-memory schema graph used during analysis. * Entities are stored in a Map for O(1) lookup by name. */ interface SchemaGraph { entities: Map; orm: string; relations: SchemaRelation[]; } /** * JSON-safe version of SchemaGraph for HTML reports and API responses. * Entities are flattened to an array since Maps are not serializable. */ interface SerializedSchemaGraph { entities: SerializedSchemaEntity[]; orm: string; relations: SchemaRelation[]; } /** * JSON-safe version of SchemaEntity (omits indexes since they are * only needed during rule analysis, not in serialized output). */ interface SerializedSchemaEntity { columns: SchemaColumn[]; filePath: string; name: string; relations: SchemaRelation[]; tableName: string; } //#endregion //#region src/common/scope.d.ts /** * How much of a scan gets reported: everything, the changed files, the changed * lines, or what the change introduced. Every mode analyses the whole project. */ type ScopeMode = "full" | "files" | "lines" | "changed"; declare const SCOPE_MODES: ScopeMode[]; declare function isScopeMode(value: string): value is ScopeMode; /** Scope metadata attached to a result so consumers can see what was reported. */ interface ScopeInfo { /** Present in `changed` mode: whether the base revision could be scanned. */ baselineAvailable?: boolean; baseRef?: string; /** Files the scope narrowed to, not the change's total file count. */ changedFiles?: number; /** Files the change touched before filtering, when the caller knows it. */ changedFilesTotal?: number; /** Set when the requested mode could not be honoured. */ degradedFrom?: ScopeMode; /** Present in `changed` mode: findings the change resolved. */ fixed?: number; mode: ScopeMode; } //#endregion //#region src/common/result.d.ts interface Score { label: string; value: number; } interface ProjectInfo { fileCount: number; framework: "express" | "fastify" | null; moduleCount: number; name: string; nestVersion: string | null; orm: string | null; } interface DiagnoseSummary { byCategory: Record; errors: number; info: number; total: number; warnings: number; } interface RuleErrorInfo { error: string; ruleId: string; } interface DiagnoseResult { diagnostics: Diagnostic[]; elapsedMs: number; endpoints?: EndpointGraph; project: ProjectInfo; ruleErrors: RuleErrorInfo[]; schema?: SerializedSchemaGraph; /** What `diagnostics` and `summary` cover. Absent when nothing was narrowed. */ scope?: ScopeInfo; score: Score; summary: DiagnoseSummary; } interface SubProjectResult { name: string; result: DiagnoseResult; } interface MonorepoResult { combined: DiagnoseResult; elapsedMs: number; isMonorepo: boolean; subProjects: SubProjectResult[]; } //#endregion //#region src/common/share.d.ts /** A section the share flow can offer, with the count shown beside it. */ interface ShareSection { count: number; id: string; label: string; } interface SharedEndpoint { controllerClass: string; handlerMethod: string; httpMethod: string; routePath: string; } /** One findings category's slice: its diagnostics and its counts alone. */ interface ShareCategorySlice { findings: CodeDiagnostic[]; schemaIssues: SchemaDiagnostic[]; summary: DiagnoseSummary; } /** The module graph as a share exports it: no timings, relative paths. */ interface SharedModules { bootstrapRoots?: string[]; circularDeps: string[][]; edges: Array<{ from: string; to: string; }>; modules: Array & { filePath: string; }>; projects: string[]; } interface SharedSchema { entities: Array & { filePath: string; }>; orm: string; relations: SchemaRelation[]; } /** * Everything the report page needs to assemble a shared payload without * deciding anything about its shape: the sections, each section's slice, * and the payload constants. */ interface ShareManifest { endpoints?: SharedEndpoint[]; filename: string; findingsByCategory: Partial>; modules?: SharedModules; /** Offered to the share when the score section is picked. */ project: ProjectInfo; schema?: SharedSchema; /** What the scan's diagnostics covered, when anything was narrowed. */ scope?: ScopeInfo; score: Score; sections: ShareSection[]; version: number; } //#endregion //#region src/common/timings.d.ts /** One class's construction time during a captured bootstrap, in milliseconds. */ interface ClassTiming { id: string; initTime: number; name: string; type: string; } /** One lifecycle hook's total duration for one class, in milliseconds. */ interface HookTiming { count?: number; hook: string; ms: number; /** Offset from bootstrap start, when captured and the hook ran once. */ startMs?: number; } /** Cumulative milliseconds from bootstrap start to the end of each phase. */ interface BootPhases { createMs?: number; initMs?: number; moduleInitMs?: number; } /** One class in the boot trace: its timing plus the classes it injects. */ interface TraceNode { deps: string[]; hooks?: HookTiming[]; initTime: number; name: string; type: string; } interface BootstrapTimings { byModule: Map; hooksByClass: Map; phases?: BootPhases; startupMs?: number; trace: Record; } //#endregion //#region src/common/artifact.d.ts /** * Version of the report artifact shape. Bump when a field changes meaning; * additive fields do not bump. Consumers narrow on this literal after * checking it. */ declare const REPORT_ARTIFACT_VERSION = 1; /** How much scanned source text an artifact embeds. */ type SourceInclusion = "none" | "touched" | "all"; /** A rule's bad/good example pair, keyed by rule id. */ type RuleExampleMap = Record; /** A provider as any UI needs it: no ts-morph node, safe to serialise. */ interface ReportProvider { dependencies: string[]; filePath: string; /** Owning module, prefixed with the sub-project in a monorepo. */ module?: string; name: string; project?: string; publicMethodCount: number; scope?: "request" | "transient"; } interface SerializedModuleNode { controllers: string[]; dynamicImports?: Record; exports: string[]; filePath: string; hookTimings?: HookTiming[]; imports: string[]; initTimings?: ClassTiming[]; isGlobal?: boolean; line?: number; name: string; project?: string; providers: string[]; providerTokens?: string[]; } interface SerializedModuleGraph { bootstrapRoots?: string[]; circularDepRecommendations: Record; circularDeps: string[][]; edges: Array<{ from: string; to: string; }>; modules: SerializedModuleNode[]; phases?: BootPhases; projects: string[]; startupMs?: number; timingsAvailable?: boolean; timingsTrace?: Record; } /** * Everything an interactive report needs, as one plain-JSON document. * The engine produces it; HTML, `--format report-json`, and any future UI * consume the same bytes. */ interface ReportArtifact { diagnostics: Diagnostic[]; elapsedMs: number; endpoints: EndpointGraph; examples: RuleExampleMap; generatedAt: string; generator: { name: "nestjs-doctor"; version: string; }; graph: SerializedModuleGraph; monorepo: boolean; project: ProjectInfo; providers: ReportProvider[]; ruleErrors: RuleErrorInfo[]; schema: SerializedSchemaGraph; schemaVersion: typeof REPORT_ARTIFACT_VERSION; /** What `diagnostics` covers. Absent when nothing was narrowed. */ scope?: ScopeInfo; score: Score; /** Precomputed share slices, so the page merges instead of rebuilding. */ share: ShareManifest; /** Full source text keyed by absolute posix path. */ sources: Record; summary: DiagnoseSummary; } //#endregion //#region src/common/config.d.ts interface RuleOverride { enabled?: boolean; excludeClasses?: string[]; options?: Record; severity?: Severity; /** Replaces the rule's own `meta.surfaces`. */ surfaces?: DiagnosticSurface[]; } interface NestjsDoctorIgnoreConfig { files?: string[]; rules?: string[]; } interface NestjsDoctorReportConfig { telemetry?: boolean; } interface NestjsDoctorConfig { categories?: Partial>; customRulesDir?: string; exclude?: string[]; ignore?: NestjsDoctorIgnoreConfig; include?: string[]; minScore?: number; report?: NestjsDoctorReportConfig; rules?: Record; telemetry?: boolean; } //#endregion //#region src/common/errors.d.ts declare class NestjsDoctorError extends Error { constructor(message: string); } declare class ConfigurationError extends NestjsDoctorError { constructor(message: string); } declare class ScanError extends NestjsDoctorError { constructor(message: string); } declare class ValidationError extends NestjsDoctorError { constructor(message: string); } //#endregion //#region src/engine/graph/tsconfig-paths.d.ts type PathAliasMap = Map; //#endregion //#region src/engine/graph/type-resolver.d.ts interface ProviderInfo { classDeclaration: ClassDeclaration; dependencies: string[]; filePath: string; name: string; publicMethodCount: number; /** Absent for the default singleton scope. */ scope?: "request" | "transient"; } declare function updateProvidersForFile(providers: Map, project: Project, filePath: string): void; //#endregion //#region src/engine/graph/module-graph.d.ts interface ModuleNode { /** Absent once the graph is detached. */ classDeclaration?: ClassDeclaration; controllers: string[]; /** Import name → the dynamic method it was imported with, e.g. `forRoot`. */ dynamicImports?: Record; exports: string[]; filePath: string; /** Every declaration file, when same-name variants were unioned. */ filePaths?: string[]; forwardRefImports: Set; imports: string[]; isGlobal: boolean; /** Line of the class declaration. Absent when the graph was built without one. */ line?: number; name: string; /** Import name → its bare package specifier, when not workspace code. */ packageImports?: Record; /** Sub-project this module belongs to. Set by `mergeModuleGraphs`. */ project?: string; providers: string[]; /** `provide` tokens of object-literal providers, which `providers` keeps as raw text. */ providerTokens: string[]; } interface ModuleGraph { edges: Map>; modules: Map; providerToModule: Map; } declare function updateModuleGraphForFile(graph: ModuleGraph, project: Project, filePath: string, pathAliases?: PathAliasMap): void; //#endregion //#region src/engine/rules/types.d.ts interface RuleMeta { category: Category; description: string; help: string; id: string; scope?: RuleScope; severity: Severity; /** * Where the rule's diagnostics may appear. Omitted means every surface. * `["cli"]` reports without touching the score or failing a build. */ surfaces?: readonly DiagnosticSurface[]; /** * Labels stamped onto every diagnostic the rule emits. `module-graph` * marks module wiring rules for the report's problems drawer. */ tags?: readonly string[]; } /** Guard facts a single file cannot see. Absent means "not determined". */ interface GuardFacts { /** Decorator names whose implementation composes `UseGuards`. */ composedDecorators: ReadonlySet; /** Some module registers a guard through `APP_GUARD`. */ globallyRegistered: boolean; /** Base classes some subclass guards, so the base's handlers are covered. */ guardedBaseClasses: ReadonlySet; } interface CodeRuleContext { config?: NestjsDoctorConfig; /** Classes NestJS instantiates itself, which one file cannot enumerate. */ diProviders?: ReadonlySet; filePath: string; guards?: GuardFacts; /** Directories that hold a module file, for boundary checks. */ moduleDirectories?: ReadonlySet; report(diagnostic: Omit): void; sourceFile: SourceFile; } interface ProjectRuleContext { config: NestjsDoctorConfig; files: string[]; /** Where `node_modules` lives, when that is not `targetPath`. */ installRoot?: string; moduleGraph: ModuleGraph; project: Project; providers: Map; report(diagnostic: Omit): void; targetPath: string; } interface SchemaRuleContext { orm: string; report(diagnostic: Omit): void; schemaGraph: SchemaGraph; } interface Rule { check(context: CodeRuleContext): void; meta: RuleMeta; } interface ProjectRule { check(context: ProjectRuleContext): void; meta: RuleMeta; } interface SchemaRule { check(context: SchemaRuleContext): void; meta: RuleMeta; } type AnyRule = Rule | ProjectRule | SchemaRule; //#endregion //#region src/engine/config/scan-config.d.ts interface ScanConfig { combinedRules: AnyRule[]; config: NestjsDoctorConfig; customRuleWarnings: string[]; fileRules: Rule[]; /** Where to resolve `node_modules` from, when not the scanned path. */ installRoot?: string; projectRules: ProjectRule[]; schemaRules: SchemaRule[]; } declare function resolveScanConfig(targetPath: string, configPath?: string): Promise; //#endregion //#region src/engine/project-detector.d.ts interface MonorepoInfo { projects: Map; } //#endregion //#region src/engine/git.d.ts /** A contiguous run of lines on the new side of a diff hunk. */ interface LineRange { end: number; start: number; } interface GitRepo { /** Scanned directory relative to {@link root}, posix, `""` at the root. */ prefix: string; /** Absolute path of the repository root, as git reports it. */ root: string; /** Absolute path of the directory being scanned, as the caller gave it. */ targetPath: string; } /** Resolves the repository that contains `targetPath`, or `null` if there is none. */ declare function findGitRepo(targetPath: string): GitRepo | null; /** * Picks the ref to compare against: explicit, then `GITHUB_BASE_REF`, then the * remote's default branch, then conventional names. `null` if none resolve. */ declare function resolveBaseRef(repo: GitRepo, explicit?: string): string | null; /** Files added, modified, or renamed between the merge base of `base` and HEAD. */ declare function getChangedFiles(repo: GitRepo, base: string): string[] | null; /** Files staged in the index — the set a pre-commit hook should look at. */ declare function getStagedFiles(repo: GitRepo): string[] | null; /** New-side line ranges introduced between the merge base of `base` and HEAD. */ declare function getChangedLineRanges(repo: GitRepo, base: string): Map | null; interface BaseCheckout { /** Removes the temporary worktree. Safe to call more than once. */ cleanup(): void; /** Absolute path mirroring the scanned directory at the base revision. */ targetPath: string; } /** * Checks the base revision out into a detached worktree under the OS temp * directory. `null` when the base is unreachable. */ declare function checkoutBase(repo: GitRepo, base: string): BaseCheckout | null; //#endregion //#region src/engine/scope.d.ts interface ScopeOptions { /** Git ref to compare against. Auto-detected when omitted. */ base?: string; /** Path to a newline-separated list of changed files (CI hand-off). */ changedFilesFrom?: string; mode: ScopeMode; /** Compare against the index instead of a ref. */ staged?: boolean; targetPath: string; } interface ResolvedScope { baseRef: string | null; /** Absolute paths of the changed files, or `null` in `full` mode. */ files: Set | null; lineRanges: Map | null; /** The mode actually in force — may be a degraded `requestedMode`. */ mode: ScopeMode; repo: GitRepo | null; requestedMode: ScopeMode; warnings: string[]; } /** * Works out which files, and lines, the reported set narrows to. Every failure * path degrades to a wider scope with a warning. */ declare function resolveScope(options: ScopeOptions): ResolvedScope; /** Narrows a diagnostic set to the resolved scope. `changed` is applied by the caller. */ declare function applyScope(diagnostics: Diagnostic[], scope: ResolvedScope): Diagnostic[]; /** Builds the {@link ScopeInfo} recorded on a result. */ declare function buildScopeInfo(scope: ResolvedScope, extra?: { baselineAvailable?: boolean; fixed?: number; }): ScopeInfo | undefined; //#endregion //#region src/engine/baseline.d.ts interface BaselineDelta { /** False when the base could not be checked out — callers should degrade. */ available: boolean; /** Findings the change resolved. */ fixed: number; /** Findings with no counterpart at the base. */ introduced: Diagnostic[]; warnings: string[]; } /** * Which of HEAD's findings the change introduced. `available: false` when the * base revision cannot be materialised. */ declare function computeBaselineDelta(headDiagnostics: Diagnostic[], scope: ResolvedScope, targetPath: string, scanConfig: ScanConfig, monorepo?: MonorepoInfo): Promise; //#endregion //#region src/engine/fingerprint.d.ts /** Path of `filePath` relative to `targetPath`, always with forward slashes. */ declare function toRelativePath(targetPath: string, filePath: string): string; /** * Stable identity for a diagnostic: rule, path, message, and the anchor line's * text. Excludes line and column, which shift under unrelated edits. */ declare function diagnosticIdentity(diagnostic: Diagnostic, targetPath: string): string; /** Hex digest of {@link diagnosticIdentity} — the form reporters emit. */ declare function fingerprint(diagnostic: Diagnostic, targetPath: string): string; /** Counts identities, so repeated findings subtract one at a time. */ declare function countIdentities(diagnostics: Diagnostic[], targetPath: string): Map; interface DiagnosticDelta { /** Findings present at the base that are gone at HEAD. */ fixed: number; /** Findings at HEAD with no counterpart at the base. */ introduced: Diagnostic[]; } /** * Subtracts the base revision's findings from HEAD's. Each side's identities * are computed against its own root. */ declare function diffDiagnostics(head: Diagnostic[], base: Diagnostic[], targetPath: string, baseTargetPath: string): DiagnosticDelta; //#endregion //#region src/engine/graph/endpoint-graph.d.ts declare function buildEndpointGraph(project: Project, files: string[], providers: Map): EndpointGraph; /** * Layer 2: traces method-level call chains for a specific endpoint. * Returns the full recursive call tree through injected dependencies. */ declare function traceEndpointCalls(endpoint: EndpointNode, providers: Map, project: Project): MethodCallNode[]; declare function updateEndpointGraphForFile(graph: EndpointGraph, project: Project, filePath: string, providers: Map): void; //#endregion //#region src/engine/rules/index.d.ts declare function getRules(): AnyRule[]; //#endregion //#region src/engine/graph/guard-decorators.d.ts /** Decorator names that compose `UseGuards`, keyed by the file declaring them. */ type GuardDecoratorIndex = Map>; //#endregion //#region src/engine/analysis-context.d.ts interface AnalysisContext { astProject: Project; config: NestjsDoctorConfig; endpointGraph: EndpointGraph; fileRules: Rule[]; files: string[]; guardDecorators: GuardDecoratorIndex; installRoot?: string; moduleGraph: ModuleGraph; pathAliases: PathAliasMap; project: ProjectInfo; projectRules: ProjectRule[]; providers: Map; schemaGraph?: SchemaGraph; schemaRules: SchemaRule[]; targetPath: string; } type AnalysisPhase = "collecting" | "parsing" | "analyzing"; /** Reports where the context build is. Counts come with "parsing" and "analyzing". */ type AnalysisProgress = (phase: AnalysisPhase, parsed?: number, total?: number) => void; declare function buildAnalysisContext(targetPath: string, scanConfig: ScanConfig, onProgress?: AnalysisProgress): Promise; declare function prepareAnalysis(targetPath: string, options?: { config?: string; }): Promise<{ context: AnalysisContext; customRuleWarnings: string[]; }>; declare function updateFile(context: AnalysisContext, filePath: string): void; //#endregion //#region src/engine/diagnostician.d.ts interface RawDiagnosticOutput { diagnostics: Diagnostic[]; elapsedMs: number; ruleErrors: RuleErrorInfo[]; } declare function checkFile(context: AnalysisContext, filePath: string): { diagnostics: Diagnostic[]; errors: RuleErrorInfo[]; }; declare function checkAllFiles(context: AnalysisContext): { diagnostics: Diagnostic[]; errors: RuleErrorInfo[]; }; declare function checkProject(context: AnalysisContext): { diagnostics: Diagnostic[]; errors: RuleErrorInfo[]; }; declare function checkSchema(context: AnalysisContext): { diagnostics: Diagnostic[]; errors: RuleErrorInfo[]; }; //#endregion //#region src/engine/result-builder.d.ts interface EngineResult { customRuleWarnings: string[]; files: string[]; moduleGraph: ModuleGraph; providers: Map; result: DiagnoseResult; schemaGraph: SchemaGraph; } interface MonorepoEngineResult { customRuleWarnings: string[]; moduleGraphs: Map; result: MonorepoResult; } /** * Replaces a result's diagnostics and recomputes the summary. The score is * carried over: it measures the project, not the reported subset. */ declare function withScopedDiagnostics(result: DiagnoseResult, diagnostics: Diagnostic[], scope: ScopeInfo | undefined): DiagnoseResult; declare function buildResult(context: AnalysisContext, rawOutput: RawDiagnosticOutput, customRuleWarnings?: string[]): EngineResult; //#endregion //#region src/engine/scanner.d.ts type AutoScanResult = { isMonorepo: true; monorepo: MonorepoEngineResult; } | { isMonorepo: false; single: EngineResult; }; declare function autoScan(targetPath: string, options?: { config?: string; monorepo?: MonorepoInfo; }): Promise; //#endregion //#region src/engine/schema/extract.d.ts declare function extractSchema(project: Project, files: string[], orm: string | null, targetPath: string): SchemaGraph; //#endregion //#region src/formatters/gitlab-report.d.ts interface CodeQualityIssue { check_name: string; description: string; fingerprint: string; location: { lines: { begin: number; }; path: string; }; severity: string; } /** Renders a result in the CodeClimate subset GitLab's Code Quality reads. */ declare function buildCodeQualityReport(result: DiagnoseResult, targetPath: string): CodeQualityIssue[]; //#endregion //#region src/formatters/markdown-report.d.ts /** Lets a CI job find and rewrite its own comment instead of stacking new ones. */ declare const MARKDOWN_COMMENT_MARKER = ""; interface MarkdownReportOptions { commitSha?: string; monorepo?: MonorepoResult; runUrl?: string; scope?: ScopeInfo; targetPath: string; version: string; warnings?: string[]; } /** Renders a result as the markdown a CI job posts. */ declare function buildMarkdownReport(result: DiagnoseResult, options: MarkdownReportOptions): string; //#endregion //#region src/formatters/sarif-report.d.ts type SarifLevel = "error" | "warning" | "note"; interface SarifRule { fullDescription: { text: string; }; help: { markdown: string; text: string; }; helpUri: string; id: string; name: string; properties: { problem: { severity: string; }; tags: string[]; }; shortDescription: { text: string; }; } interface SarifResult { level: SarifLevel; locations: { physicalLocation: { artifactLocation: { uri: string; uriBaseId: string; }; region: { startColumn?: number; startLine: number; }; }; }[]; message: { text: string; }; partialFingerprints: Record; ruleId: string; ruleIndex: number; } interface SarifLog { $schema: string; runs: { columnKind: string; originalUriBaseIds: Record; results: SarifResult[]; tool: { driver: { informationUri: string; name: string; rules: SarifRule[]; semanticVersion: string; version: string; }; }; }[]; version: string; } /** * Renders a result as a SARIF 2.1.0 log, with an explicit `partialFingerprints` * on every result. */ declare function buildSarifLog(result: DiagnoseResult, targetPath: string, version: string): SarifLog; //#endregion //#region src/report/artifact.d.ts interface ReportArtifactInput { bootstrapRoots?: string[]; files?: string[]; moduleGraph: ModuleGraph; monorepo?: boolean; projects?: string[]; providers?: ReportProvider[]; result: DiagnoseResult; sources?: SourceInclusion; /** Where the scan ran; share slices relativize their paths against it. */ targetPath?: string; timings?: BootstrapTimings; version: string; } /** The one place report-shaped data is assembled. */ declare function buildReportArtifact(input: ReportArtifactInput): ReportArtifact; //#endregion //#region src/api/index.d.ts /** * Scans a single NestJS project and returns a health diagnostic result. * * @param path - Path to the NestJS project root directory. * @param options - Optional configuration: `config` specifies a path to a config file. * @returns A `DiagnoseResult` containing the health score, diagnostics, and summary. * @throws {ValidationError} If the path is empty, doesn't exist, or isn't a directory. */ declare function diagnose(path: string, options?: { config?: string; }): Promise; /** * Scans a NestJS monorepo and returns per-project and combined diagnostics. * * Auto-detects monorepo structure from `nest-cli.json`. If the target is not a * monorepo, falls back to a single-project scan wrapped in the monorepo result format. * * @param path - Path to the monorepo root directory. * @param options - Optional configuration: `config` specifies a path to a config file. * @returns A `MonorepoResult` with sub-project results and combined score. * @throws {ValidationError} If the path is empty, doesn't exist, or isn't a directory. */ declare function diagnoseMonorepo(path: string, options?: { config?: string; }): Promise; //#endregion export { type AnalysisContext, type AnalysisProgress, type AnyRule, type AutoScanResult, type BaseCheckout, type BaseDiagnostic, type BaselineDelta, type Category, type CodeDiagnostic, type CodeQualityIssue, type CodeRuleContext, type CodeRuleContext as RuleContext, ConfigurationError, type DependencyType, type DiagnoseResult, type DiagnoseSummary, type Diagnostic, type DiagnosticDelta, type DiagnosticSurface, type EndpointGraph, type EndpointNode, type GitRepo, type LineRange, MARKDOWN_COMMENT_MARKER, type MarkdownReportOptions, type MethodCallNode, type MethodDependencyNode, type MonorepoResult, type NestjsDoctorConfig, NestjsDoctorError, type ProjectInfo, type ProjectRule, type ProjectRuleContext, REPORT_ARTIFACT_VERSION, type RawDiagnosticOutput, type ReportArtifact, type ReportProvider, type ResolvedScope, type Rule, type RuleErrorInfo, type RuleExampleMap, type RuleMeta, SCOPE_MODES, type SarifLog, type ScanConfig, ScanError, type SchemaColumn, type SchemaDiagnostic, type SchemaEntity, type SchemaGraph, type SchemaRelation, type SchemaRule, type SchemaRuleContext, type ScopeInfo, type ScopeMode, type ScopeOptions, type Score, type SerializedModuleGraph, type SerializedModuleNode, type SerializedSchemaGraph, type Severity, type SourceInclusion, type SubProjectResult, ValidationError, applyScope, autoScan, buildAnalysisContext, buildCodeQualityReport, buildEndpointGraph, buildMarkdownReport, buildReportArtifact, buildResult, buildSarifLog, buildScopeInfo, checkAllFiles, checkFile, checkProject, checkSchema, checkoutBase, computeBaselineDelta, countIdentities, diagnose, diagnoseMonorepo, diagnosticIdentity, diffDiagnostics, extractSchema, findGitRepo, fingerprint, forSurface, getChangedFiles, getChangedLineRanges, getRules, getStagedFiles, isCodeDiagnostic, isSchemaDiagnostic, isScopeMode, onSurface, prepareAnalysis, resolveBaseRef, resolveScanConfig, resolveScope, toRelativePath, traceEndpointCalls, updateEndpointGraphForFile, updateFile, updateModuleGraphForFile, updateProvidersForFile, withScopedDiagnostics };