/** * Smart TSConfig Tool - 83% Token Reduction * * Parses and analyzes tsconfig.json with: * - Extends chain resolution * - Compiler options inheritance * - 7-day TTL caching * - Config issue detection * - Optimization suggestions */ import { CacheEngine } from '../../core/cache-engine.js'; import { TokenCounter } from '../../core/token-counter.js'; import { MetricsCollector } from '../../core/metrics.js'; import { type Declaring } from '../shared/savings.js'; interface TsConfigCompilerOptions { target?: string; module?: string; strict?: boolean; esModuleInterop?: boolean; skipLibCheck?: boolean; forceConsistentCasingInFileNames?: boolean; moduleResolution?: string; resolveJsonModule?: boolean; isolatedModules?: boolean; jsx?: string; lib?: string[]; outDir?: string; rootDir?: string; baseUrl?: string; paths?: Record; [key: string]: unknown; } interface EmittedTsConfig { compilerOptions: TsConfigCompilerOptions; include?: string[]; exclude?: string[]; files?: string[]; references?: Array<{ path: string; }>; /** Every file the merge drew on, base first. Never fewer than two. */ extendsChain: string[]; } /** * What resolving the config actually did. * * `merged` means the config extended another and the answer is the merge of * the chain -- genuinely new, and sent. * * `as-written` means it extended nothing, so the resolved config IS the file * the caller named, which they have. Then this word is the finding and the * merge is not sent: 94 tokens of restated config against a 76-token file, * for the news that there was no news. */ type ConfigResolution = 'as-written' | 'merged'; interface ConfigIssue { severity: 'error' | 'warning' | 'info'; category: 'strict-mode' | 'target-version' | 'module-system' | 'paths' | 'performance' | 'compatibility'; message: string; suggestion?: string; } interface SmartTsConfigOptions { configPath?: string; projectRoot?: string; includeIssues?: boolean; includeSuggestions?: boolean; maxCacheAge?: number; } interface SmartTsConfigOutput { success: boolean; configPath: string; resolution: ConfigResolution; /** * The merge -- PRESENT ONLY when `resolution` is `merged`. * * There is nothing to send when nothing was merged. The analysis still * travels: `issues` and `suggestions` are computed from the resolved * config either way, and they are what the caller could not have worked * out from the file in front of them. */ resolved?: EmittedTsConfig; issues?: ConfigIssue[]; suggestions?: string[]; cacheHit: boolean; diff?: { added: string[]; removed: string[]; modified: string[]; }; } declare class SmartTsConfig { private cache; private metrics; private projectRoot; constructor(cache: CacheEngine, _tokenCounter: TokenCounter, metrics: MetricsCollector, projectRoot?: string); /** * Main entry point - parse and resolve tsconfig */ run(options?: SmartTsConfigOptions): Promise>; /** * Resolve config path from options or find default */ private resolveConfigPath; /** * Resolve tsconfig with extends chain */ private resolveConfig; /** * Re-reads every file a cached resolution was merged from. * * The cache key covers the leaf config's hash only, so a base config that * changed since would otherwise be served from a stale merge -- the answer * would be wrong in precisely the fields the caller came here for. Returns * undefined when any file in the chain has gone, which invalidates the entry. */ private readChain; /** * Parse a single tsconfig file */ private parseConfigFile; private stripJsonComments; /** * Resolve extends path (can be relative or node_modules package) */ private resolveExtendsPath; /** * Merge two configs (later overrides earlier) */ private mergeConfigs; /** * Detect configuration issues */ private detectIssues; /** * Generate optimization suggestions */ private generateSuggestions; private transformOutput; /** * Close resources */ close(): void; } /** * Factory function for shared resources (benchmarks) */ export declare function getSmartTsConfig(cache: CacheEngine, tokenCounter: TokenCounter, metrics: MetricsCollector, projectRoot?: string): SmartTsConfig; /** * Smart TSConfig - Parse and analyze tsconfig.json with caching * * @param options - Configuration options * @returns Parsed and resolved tsconfig with metrics */ export declare function runSmartTsconfig(options?: SmartTsConfigOptions): Promise>; export declare const SMART_TSCONFIG_TOOL_DEFINITION: { readonly name: "smart_tsconfig"; readonly description: "Parse and analyze TypeScript configuration. Resolves extends chains, detects issues, and caches results for 7 days. Measured token reduction vs reading the file: 40-92% first read, 40-92% repeated (bench/tools, 3 fixtures) -- it answers what the resolved config is and what is wrong with it, and sends the merge only where there was one: a config that extends nothing is answered with that fact and its suggestions, because the caller already holds the file."; readonly inputSchema: { readonly type: "object"; readonly properties: { readonly configPath: { readonly type: "string"; readonly description: "Path to tsconfig.json (relative to projectRoot)"; }; readonly projectRoot: { readonly type: "string"; readonly description: "Project root directory (defaults to cwd)"; }; readonly includeIssues: { readonly type: "boolean"; readonly description: "Include configuration issues detection (default: true)"; }; readonly includeSuggestions: { readonly type: "boolean"; readonly description: "Include optimization suggestions (default: true)"; }; readonly maxCacheAge: { readonly type: "number"; readonly description: "Maximum cache age in seconds (default: 604800 = 7 days)"; }; }; }; }; export {}; //# sourceMappingURL=smart-tsconfig.d.ts.map