@kb-labs/quality-core 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/dead-code/entry-points.ts","../../src/dead-code/import-graph.ts","../../src/dead-code/scan-dead-files.ts","../../src/dead-code/backup.ts"],"names":["path","fs","exports","globby"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Entry point collection for dead code detection\n *\n * Collects all files that are \"alive by definition\" — entry points from\n * package.json, tsup.config.ts, manifest.ts, tests, and configs.\n *\n * Fail-open: if we can't parse a config, we emit a warning and treat\n * ALL files in the package as alive (zero false positives).\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport globby from 'globby';\n\nexport interface EntryPointResult {\n /** Absolute paths of entry point files (roots for BFS) */\n entryFiles: Set<string>;\n /** Files alive by convention (tests, configs) — not part of graph traversal */\n aliveByConvention: Set<string>;\n /** Non-fatal issues during parsing */\n warnings: string[];\n /** If true, couldn't parse configs — all files should be treated as alive */\n failOpen: boolean;\n}\n\n// Config file basenames that are always alive\nconst CONFIG_FILE_PATTERNS = [\n 'tsup.config.ts',\n 'tsup.config.mts',\n 'tsup.config.js',\n 'tsup.config.mjs',\n 'tsup.bin.config.ts',\n 'tsup.lib.config.ts',\n 'vitest.config.ts',\n 'vitest.config.mts',\n 'vitest.config.js',\n 'jest.config.ts',\n 'jest.config.js',\n 'eslint.config.js',\n 'eslint.config.mjs',\n 'vitest.setup.ts',\n 'vitest.setup.js',\n];\n\n/**\n * Collect all entry points for a package.\n *\n * A file is an entry point if it's referenced by package.json, tsup.config.ts,\n * or manifest.ts. Tests and config files are always alive by convention.\n */\nexport async function collectEntryPoints(\n packageDir: string,\n packageJson: Record<string, unknown>,\n): Promise<EntryPointResult> {\n const entryFiles = new Set<string>();\n const aliveByConvention = new Set<string>();\n const warnings: string[] = [];\n let failOpen = false;\n\n // 1. package.json entries\n collectPackageJsonEntries(packageDir, packageJson, entryFiles, warnings);\n\n // 2. tsup.config.ts entries\n const tsupOk = await collectTsupEntries(packageDir, entryFiles, warnings);\n if (!tsupOk) {\n failOpen = true;\n }\n\n // 3. manifest.ts handler paths\n collectManifestHandlers(packageDir, entryFiles, warnings);\n\n // 4. Dynamic imports (string literal only)\n await collectDynamicImportTargets(packageDir, entryFiles, warnings);\n\n // 5. Test files — always alive\n await collectTestFiles(packageDir, aliveByConvention);\n\n // 6. Config files — always alive\n collectConfigFiles(packageDir, aliveByConvention);\n\n // Fallback: if no entry points found at all, use src/index.ts\n if (entryFiles.size === 0) {\n const defaultEntry = path.join(packageDir, 'src', 'index.ts');\n if (fs.existsSync(defaultEntry)) {\n entryFiles.add(defaultEntry);\n warnings.push('No entry points found, using src/index.ts as default');\n }\n }\n\n return { entryFiles, aliveByConvention, warnings, failOpen };\n}\n\n/**\n * Map a dist/ path to its src/ counterpart.\n * dist/index.js → src/index.ts\n * dist/sandbox/bootstrap.js → src/sandbox/bootstrap.ts\n */\nexport function distPathToSrcPath(\n distPath: string,\n packageDir: string,\n): string | null {\n // Normalize the path — remove leading ./ if present\n let normalized = distPath.replace(/^\\.?\\/?/, '');\n\n // Replace dist/ prefix with src/\n if (normalized.startsWith('dist/') || normalized.startsWith('dist\\\\')) {\n normalized = 'src/' + normalized.slice(5);\n }\n\n // Replace extensions\n normalized = normalized\n .replace(/\\.d\\.ts$/, '.ts')\n .replace(/\\.js$/, '.ts')\n .replace(/\\.mjs$/, '.ts')\n .replace(/\\.cjs$/, '.ts');\n\n const absolute = path.resolve(packageDir, normalized);\n\n if (fs.existsSync(absolute)) {\n return absolute;\n }\n\n // Try index.ts fallback (for directory-style entries)\n const indexPath = path.join(absolute.replace(/\\.ts$/, ''), 'index.ts');\n if (fs.existsSync(indexPath)) {\n return indexPath;\n }\n\n return null;\n}\n\n// --- Internal helpers ---\n\nfunction collectPackageJsonEntries(\n packageDir: string,\n pkgJson: Record<string, unknown>,\n entryFiles: Set<string>,\n warnings: string[],\n): void {\n // main, module, types fields\n for (const field of ['main', 'module', 'types', 'typings']) {\n const value = pkgJson[field];\n if (typeof value === 'string') {\n const srcPath = distPathToSrcPath(value, packageDir);\n if (srcPath) {\n entryFiles.add(srcPath);\n }\n }\n }\n\n // bin field (string or object)\n const bin = pkgJson['bin'];\n if (typeof bin === 'string') {\n const srcPath = distPathToSrcPath(bin, packageDir);\n if (srcPath) {entryFiles.add(srcPath);}\n } else if (bin && typeof bin === 'object') {\n for (const value of Object.values(bin as Record<string, string>)) {\n if (typeof value === 'string') {\n const srcPath = distPathToSrcPath(value, packageDir);\n if (srcPath) {entryFiles.add(srcPath);}\n }\n }\n }\n\n // exports field\n const exports = pkgJson['exports'];\n if (exports && typeof exports === 'object') {\n collectExportsEntries(\n packageDir,\n exports as Record<string, unknown>,\n entryFiles,\n warnings,\n );\n }\n}\n\nfunction collectExportsEntries(\n packageDir: string,\n exports: Record<string, unknown>,\n entryFiles: Set<string>,\n _warnings: string[],\n): void {\n for (const [key, value] of Object.entries(exports)) {\n // Skip wildcard catch-all\n if (key.includes('*')) {continue;}\n\n const importPath = extractImportPath(value);\n if (importPath) {\n const srcPath = distPathToSrcPath(importPath, packageDir);\n if (srcPath) {\n entryFiles.add(srcPath);\n }\n }\n }\n}\n\nfunction extractImportPath(value: unknown): string | null {\n if (typeof value === 'string') {return value;}\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n // Try import, then default, then require\n for (const key of ['import', 'default', 'require']) {\n if (typeof obj[key] === 'string') {return obj[key] as string;}\n }\n }\n return null;\n}\n\nasync function collectTsupEntries(\n packageDir: string,\n entryFiles: Set<string>,\n warnings: string[],\n): Promise<boolean> {\n // Find tsup config files\n const tsupConfigs = [\n 'tsup.config.ts',\n 'tsup.config.mts',\n 'tsup.config.js',\n 'tsup.config.mjs',\n 'tsup.bin.config.ts',\n 'tsup.lib.config.ts',\n ];\n\n let foundAny = false;\n\n for (const configName of tsupConfigs) {\n const configPath = path.join(packageDir, configName);\n if (!fs.existsSync(configPath)) {continue;}\n\n foundAny = true;\n\n try {\n const content = fs.readFileSync(configPath, 'utf-8');\n const entries = parseTsupEntries(content);\n\n for (const entry of entries) {\n // Check if it's a glob\n if (entry.includes('*') || entry.includes('{')) {\n const expanded = await globby(entry, {\n cwd: packageDir,\n absolute: true,\n });\n for (const file of expanded) {\n entryFiles.add(file);\n }\n } else {\n const absolute = path.resolve(packageDir, entry);\n if (fs.existsSync(absolute)) {\n entryFiles.add(absolute);\n }\n }\n }\n } catch {\n warnings.push(`Failed to parse ${configName}`);\n return false; // Trigger fail-open\n }\n }\n\n // No tsup config is fine — not all packages use tsup\n if (!foundAny) {return true;}\n\n return true;\n}\n\n/**\n * Parse entry points from tsup config file content.\n * Handles: string, array of strings, object of strings.\n */\nexport function parseTsupEntries(content: string): string[] {\n const entries: string[] = [];\n\n // Pattern 1: entry: 'src/index.ts'\n const singleMatch = content.match(/entry\\s*:\\s*['\"]([^'\"]+)['\"]/);\n if (singleMatch && singleMatch[1]) {\n entries.push(singleMatch[1]);\n return entries;\n }\n\n // Pattern 2: entry: ['src/index.ts', 'src/other.ts']\n // Pattern 3: entry: { index: 'src/index.ts', other: 'src/other.ts' }\n // Both can be extracted by finding all src/ paths within the entry block\n const entryBlockMatch = content.match(\n /entry\\s*:\\s*[\\[{]([\\s\\S]*?)[\\]}]/,\n );\n if (entryBlockMatch && entryBlockMatch[1]) {\n const block = entryBlockMatch[1];\n // Extract all quoted paths\n const pathPattern = /['\"]([^'\"]*?src\\/[^'\"]+)['\"]/g;\n let match;\n while ((match = pathPattern.exec(block)) !== null) {\n if (match[1]) {entries.push(match[1]);}\n }\n return entries;\n }\n\n return entries;\n}\n\nfunction collectManifestHandlers(\n packageDir: string,\n entryFiles: Set<string>,\n warnings: string[],\n): void {\n const manifestPath = path.join(packageDir, 'src', 'manifest.ts');\n if (!fs.existsSync(manifestPath)) {return;}\n\n try {\n const content = fs.readFileSync(manifestPath, 'utf-8');\n const handlers = parseManifestHandlers(content);\n\n for (const handlerPath of handlers) {\n // Handler paths are like './cli/commands/run.js#default'\n // Strip the #export suffix\n const pathOnly = handlerPath.split('#')[0] ?? handlerPath;\n // Map .js → .ts and prepend src/\n const srcRelative = 'src/' + pathOnly.replace(/^\\.\\//, '').replace(/\\.js$/, '.ts');\n const absolute = path.resolve(packageDir, srcRelative);\n\n if (fs.existsSync(absolute)) {\n entryFiles.add(absolute);\n }\n }\n\n // Also mark manifest.ts itself as an entry point\n entryFiles.add(manifestPath);\n } catch {\n warnings.push('Failed to parse manifest.ts');\n }\n}\n\n/**\n * Extract handler paths from manifest.ts content.\n * Matches: handler: './path/to/file.js#export' and handlerPath: './path/to/file.js'\n */\nexport function parseManifestHandlers(content: string): string[] {\n const handlers: string[] = [];\n const seen = new Set<string>();\n\n // Match handler: './path.js#export' and handlerPath: './path.js'\n const pattern = /(?:handler|handlerPath)\\s*:\\s*['\"]([^'\"]+)['\"]/g;\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const matchValue = match[1];\n if (!matchValue) {continue;}\n const raw = matchValue.split('#')[0] ?? matchValue;\n if (!seen.has(raw)) {\n seen.add(raw);\n handlers.push(raw);\n }\n }\n\n return handlers;\n}\n\nasync function collectDynamicImportTargets(\n packageDir: string,\n entryFiles: Set<string>,\n _warnings: string[],\n): Promise<void> {\n const srcDir = path.join(packageDir, 'src');\n if (!fs.existsSync(srcDir)) {return;}\n\n const sourceFiles = await globby('**/*.{ts,tsx}', {\n cwd: srcDir,\n absolute: true,\n ignore: ['**/*.test.ts', '**/*.spec.ts', '**/__tests__/**'],\n });\n\n // Only extract string-literal dynamic imports (not template literals)\n const dynamicImportPattern = /import\\s*\\(\\s*['\"](\\.[^'\"]+)['\"]\\s*\\)/g;\n\n for (const file of sourceFiles) {\n try {\n const content = fs.readFileSync(file, 'utf-8');\n let match;\n while ((match = dynamicImportPattern.exec(content)) !== null) {\n const importPath = match[1];\n if (!importPath) {continue;}\n const resolved = resolveFilePath(importPath, file);\n if (resolved) {\n entryFiles.add(resolved);\n }\n }\n } catch {\n // Skip unreadable files\n }\n }\n}\n\nasync function collectTestFiles(\n packageDir: string,\n aliveByConvention: Set<string>,\n): Promise<void> {\n const srcDir = path.join(packageDir, 'src');\n if (!fs.existsSync(srcDir)) {return;}\n\n const testFiles = await globby(\n ['**/*.test.ts', '**/*.test.tsx', '**/*.spec.ts', '**/*.spec.tsx', '**/__tests__/**/*.ts'],\n { cwd: srcDir, absolute: true },\n );\n\n for (const file of testFiles) {\n aliveByConvention.add(file);\n }\n}\n\nfunction collectConfigFiles(\n packageDir: string,\n aliveByConvention: Set<string>,\n): void {\n for (const pattern of CONFIG_FILE_PATTERNS) {\n const configPath = path.join(packageDir, pattern);\n if (fs.existsSync(configPath)) {\n aliveByConvention.add(configPath);\n }\n }\n}\n\n/**\n * Resolve a relative import path to an absolute file path.\n * Handles ESM convention: import from './foo.js' → ./foo.ts\n */\nfunction resolveFilePath(\n importPath: string,\n fromFile: string,\n): string | null {\n const dir = path.dirname(fromFile);\n const base = path.resolve(dir, importPath);\n\n // Try direct with .js → .ts mapping\n const tsPath = base.replace(/\\.js$/, '.ts');\n if (fs.existsSync(tsPath)) {return tsPath;}\n if (fs.existsSync(base)) {return base;}\n\n // Try with .ts extension\n if (fs.existsSync(base + '.ts')) {return base + '.ts';}\n if (fs.existsSync(base + '.tsx')) {return base + '.tsx';}\n\n // Try as directory with index.ts\n if (fs.existsSync(path.join(base, 'index.ts'))) {\n return path.join(base, 'index.ts');\n }\n\n return null;\n}\n","/**\n * File-level import graph and BFS reachability analysis\n *\n * Builds a directed graph of file → imported files, then walks from\n * entry points to find all reachable (alive) files.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Import extraction regex patterns.\n * Tested across 350K+ LOC by devkit (devkit-check-imports.mjs).\n */\nconst IMPORT_PATTERNS: RegExp[] = [\n // Static imports: import X from 'module', import { X } from 'module', import 'module'\n /import\\s+(?:[\\w*{}\\n\\r\\t, ]+\\s+from\\s+)?['\"]([^'\"]+)['\"]/g,\n\n // Dynamic imports (string literal): import('./module'), import(\"./module\")\n /import\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g,\n\n // CommonJS require: require('./module'), require(\"./module\")\n /require\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g,\n\n // Re-exports: export { X } from 'module', export * from 'module'\n /export\\s+(?:[\\w*{}\\n\\r\\t, ]+\\s+)?from\\s+['\"]([^'\"]+)['\"]/g,\n];\n\n/**\n * Extensions to try when resolving imports, in priority order.\n */\nconst RESOLVE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];\n\n/**\n * Extract all import paths from a source file's content.\n * Returns raw import specifiers (both relative and package).\n */\nexport function extractFileImports(content: string): string[] {\n const imports: string[] = [];\n\n for (const pattern of IMPORT_PATTERNS) {\n // Reset regex state (global flag)\n pattern.lastIndex = 0;\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const specifier = match[1];\n if (specifier) {\n imports.push(specifier);\n }\n }\n }\n\n return imports;\n}\n\n/**\n * Check if an import specifier is a relative/local import.\n */\nexport function isRelativeImport(specifier: string): boolean {\n return specifier.startsWith('./') || specifier.startsWith('../');\n}\n\n/**\n * Resolve a relative import to an absolute file path.\n *\n * Handles ESM convention where source code imports './foo.js'\n * but the actual file is './foo.ts'.\n */\nexport function resolveRelativeImport(\n specifier: string,\n sourceFile: string,\n): string | null {\n const dir = path.dirname(sourceFile);\n const basePath = path.resolve(dir, specifier);\n\n // 1. ESM convention: strip .js and try .ts\n if (specifier.endsWith('.js')) {\n const tsPath = basePath.slice(0, -3) + '.ts';\n if (fs.existsSync(tsPath)) {return tsPath;}\n const tsxPath = basePath.slice(0, -3) + '.tsx';\n if (fs.existsSync(tsxPath)) {return tsxPath;}\n }\n\n // 2. Exact match\n if (fs.existsSync(basePath) && fs.statSync(basePath).isFile()) {\n return basePath;\n }\n\n // 3. Try adding extensions\n for (const ext of RESOLVE_EXTENSIONS) {\n const withExt = basePath + ext;\n if (fs.existsSync(withExt)) {return withExt;}\n }\n\n // 4. Try as directory with index file\n if (fs.existsSync(basePath) && fs.statSync(basePath).isDirectory()) {\n for (const ext of RESOLVE_EXTENSIONS) {\n const indexPath = path.join(basePath, 'index' + ext);\n if (fs.existsSync(indexPath)) {return indexPath;}\n }\n }\n\n // 5. Try as directory without existing check (basePath might not have extension)\n for (const ext of RESOLVE_EXTENSIONS) {\n const indexPath = path.join(basePath, 'index' + ext);\n if (fs.existsSync(indexPath)) {return indexPath;}\n }\n\n return null;\n}\n\n/**\n * Build a file-level import graph for all source files.\n *\n * Returns a map: absolute file path → set of absolute imported file paths.\n * Only includes relative imports (not external packages).\n */\nexport function buildFileImportGraph(\n sourceFiles: string[],\n): Map<string, Set<string>> {\n const graph = new Map<string, Set<string>>();\n\n for (const file of sourceFiles) {\n const deps = new Set<string>();\n graph.set(file, deps);\n\n try {\n const content = fs.readFileSync(file, 'utf-8');\n const imports = extractFileImports(content);\n\n for (const specifier of imports) {\n if (!isRelativeImport(specifier)) {continue;}\n\n const resolved = resolveRelativeImport(specifier, file);\n if (resolved) {\n deps.add(resolved);\n }\n }\n } catch {\n // Skip unreadable files — they won't contribute edges\n }\n }\n\n return graph;\n}\n\n/**\n * BFS from entry points through the import graph.\n * Returns the set of all reachable file paths.\n */\nexport function findReachableFiles(\n entryPoints: Set<string>,\n importGraph: Map<string, Set<string>>,\n): Set<string> {\n const visited = new Set<string>();\n const queue = [...entryPoints];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n if (visited.has(current)) {continue;}\n visited.add(current);\n\n const deps = importGraph.get(current);\n if (deps) {\n for (const dep of deps) {\n if (!visited.has(dep)) {\n queue.push(dep);\n }\n }\n }\n }\n\n return visited;\n}\n\n/**\n * Count total edges in the import graph.\n */\nexport function countGraphEdges(graph: Map<string, Set<string>>): number {\n let count = 0;\n for (const deps of graph.values()) {\n count += deps.size;\n }\n return count;\n}\n","/**\n * Dead code file scanner — main orchestrator\n *\n * Per-package analysis: collect entry points, build import graph,\n * BFS reachability, report unreachable files.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport globby from 'globby';\nimport type {\n DeadCodeResult,\n DeadCodeOptions,\n PackageDeadCodeResult,\n DeadFile,\n} from '@kb-labs/quality-contracts';\nimport { collectEntryPoints } from './entry-points.js';\nimport {\n buildFileImportGraph,\n findReachableFiles,\n countGraphEdges,\n} from './import-graph.js';\n\ninterface DiscoveredPackage {\n packageDir: string;\n packageJson: Record<string, unknown>;\n packageName: string;\n}\n\n/**\n * Scan the monorepo for dead (unreachable) source files.\n *\n * For each package:\n * 1. Collect entry points (package.json, tsup, manifest, tests, configs)\n * 2. Build file-level import graph\n * 3. BFS from entry points to find reachable files\n * 4. Everything not reachable = dead\n */\nexport async function scanDeadFiles(\n rootDir: string,\n options?: DeadCodeOptions,\n): Promise<DeadCodeResult> {\n const startTime = Date.now();\n const packages = findPackagesInMonorepo(rootDir, options?.packageFilter);\n const results: PackageDeadCodeResult[] = [];\n\n for (const pkg of packages) {\n const result = await analyzePackage(pkg);\n if (result) {\n results.push(result);\n }\n }\n\n // Calculate summary\n const summary = calculateSummary(results, rootDir);\n\n return {\n packages: results,\n summary,\n duration: Date.now() - startTime,\n };\n}\n\n/**\n * Discover all packages across kb-labs-* repos.\n * Follows the same pattern as check-builds.ts findPackagesWithBuildScript().\n */\nfunction findPackagesInMonorepo(\n rootDir: string,\n filter?: string,\n): DiscoveredPackage[] {\n const packages: DiscoveredPackage[] = [];\n\n if (!fs.existsSync(rootDir)) {return packages;}\n\n const entries = fs.readdirSync(rootDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (!entry.isDirectory() || !entry.name.startsWith('kb-labs-')) {continue;}\n\n const repoPath = path.join(rootDir, entry.name);\n const packagesDir = path.join(repoPath, 'packages');\n\n if (!fs.existsSync(packagesDir)) {continue;}\n\n const packageDirs = fs.readdirSync(packagesDir, { withFileTypes: true });\n\n for (const pkgDir of packageDirs) {\n if (!pkgDir.isDirectory()) {continue;}\n\n const packageJsonPath = path.join(packagesDir, pkgDir.name, 'package.json');\n if (!fs.existsSync(packageJsonPath)) {continue;}\n\n try {\n const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const pkgName = pkgJson.name || pkgDir.name;\n const packageDir = path.join(packagesDir, pkgDir.name);\n\n // Check if src/ directory exists (skip packages without source)\n const srcDir = path.join(packageDir, 'src');\n if (!fs.existsSync(srcDir)) {continue;}\n\n // Apply filter\n if (filter && !pkgName.includes(filter) && !pkgDir.name.includes(filter)) {\n continue;\n }\n\n packages.push({ packageDir, packageJson: pkgJson, packageName: pkgName });\n } catch {\n // Skip unreadable package.json\n }\n }\n }\n\n return packages;\n}\n\n/**\n * Analyze a single package for dead files.\n */\nasync function analyzePackage(\n pkg: DiscoveredPackage,\n): Promise<PackageDeadCodeResult | null> {\n const { packageDir, packageJson, packageName } = pkg;\n const srcDir = path.join(packageDir, 'src');\n\n // Discover all source files\n const allSourceFiles = await globby('**/*.{ts,tsx}', {\n cwd: srcDir,\n absolute: true,\n ignore: ['**/*.d.ts'],\n });\n\n if (allSourceFiles.length === 0) {return null;}\n\n // Phase 1: Collect entry points\n const {\n entryFiles,\n aliveByConvention,\n warnings,\n failOpen,\n } = await collectEntryPoints(packageDir, packageJson);\n\n // Fail-open: if config parsing failed, treat all files as alive\n if (failOpen) {\n return {\n packageName,\n packageDir,\n totalFiles: allSourceFiles.length,\n aliveFiles: allSourceFiles.length,\n deadFiles: [],\n entryPoints: [...entryFiles].map(f => path.relative(packageDir, f)),\n graphEdgeCount: 0,\n warnings: [...warnings, 'FAIL-OPEN: All files treated as alive due to config parse errors'],\n };\n }\n\n // Phase 2: Build import graph\n const importGraph = buildFileImportGraph(allSourceFiles);\n const graphEdgeCount = countGraphEdges(importGraph);\n\n // Phase 3: BFS reachability from entry points\n // Seed with both entry points and convention-alive files (tests import prod code)\n const seeds = new Set([...entryFiles, ...aliveByConvention]);\n const reachable = findReachableFiles(seeds, importGraph);\n\n // Phase 4: Dead = total - reachable - aliveByConvention\n const allAlive = new Set([...reachable, ...aliveByConvention]);\n const deadFiles: DeadFile[] = [];\n\n for (const file of allSourceFiles) {\n if (!allAlive.has(file)) {\n const stats = safeFileStat(file);\n deadFiles.push({\n absolutePath: file,\n relativePath: path.relative(packageDir, file),\n packageName,\n packageDir,\n sizeBytes: stats?.size ?? 0,\n });\n }\n }\n\n // Sort dead files by path for stable output\n deadFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n\n return {\n packageName,\n packageDir,\n totalFiles: allSourceFiles.length,\n aliveFiles: allSourceFiles.length - deadFiles.length,\n deadFiles,\n entryPoints: [...entryFiles].map(f => path.relative(packageDir, f)),\n graphEdgeCount,\n warnings,\n };\n}\n\nfunction calculateSummary(\n results: PackageDeadCodeResult[],\n rootDir: string,\n): DeadCodeResult['summary'] {\n let totalFiles = 0;\n let totalDead = 0;\n let totalDeadBytes = 0;\n\n for (const pkg of results) {\n totalFiles += pkg.totalFiles;\n totalDead += pkg.deadFiles.length;\n for (const deadFile of pkg.deadFiles) {\n totalDeadBytes += deadFile.sizeBytes;\n }\n }\n\n // Find directories that would become empty after removing dead files\n const emptyDirectories = findPotentialEmptyDirs(results, rootDir);\n\n return {\n totalPackages: results.length,\n totalFiles,\n totalAlive: totalFiles - totalDead,\n totalDead,\n totalDeadBytes,\n emptyDirectories,\n };\n}\n\n/**\n * Find directories that would become empty if dead files were removed.\n */\nfunction findPotentialEmptyDirs(\n results: PackageDeadCodeResult[],\n _rootDir: string,\n): string[] {\n const emptyDirs: string[] = [];\n\n for (const pkg of results) {\n if (pkg.deadFiles.length === 0) {continue;}\n\n // Group dead files by directory\n const deadByDir = new Map<string, number>();\n for (const deadFile of pkg.deadFiles) {\n const dir = path.dirname(deadFile.absolutePath);\n deadByDir.set(dir, (deadByDir.get(dir) ?? 0) + 1);\n }\n\n // Check if removing dead files would leave the directory empty\n for (const [dir, deadCount] of deadByDir) {\n try {\n const allFiles = fs.readdirSync(dir);\n if (allFiles.length === deadCount) {\n emptyDirs.push(path.relative(pkg.packageDir, dir));\n }\n } catch {\n // Skip unreadable directories\n }\n }\n }\n\n return emptyDirs;\n}\n\nfunction safeFileStat(filePath: string): fs.Stats | null {\n try {\n return fs.statSync(filePath);\n } catch {\n return null;\n }\n}\n","/**\n * Backup, restore, and auto-removal for dead code files\n *\n * Creates timestamped backups before deletion, supports full restore,\n * and cleans up empty directories + package.json exports.\n */\n\nimport { execSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type {\n DeadCodeResult,\n DeadCodeBackupManifest,\n DeadCodeRemovalResult,\n} from '@kb-labs/quality-contracts';\n\nconst BACKUP_DIR = '.dead-code-backup';\n\n/**\n * Remove dead files with full backup.\n * Creates a timestamped backup directory, copies files, then deletes.\n */\nexport async function removeDeadFiles(\n rootDir: string,\n scanResult: DeadCodeResult,\n options?: { dryRun?: boolean },\n): Promise<DeadCodeRemovalResult> {\n const dryRun = options?.dryRun ?? false;\n\n // Generate backup ID from timestamp\n const backupId = new Date().toISOString().replace(/[:.]/g, '-');\n const backupPath = path.join(rootDir, BACKUP_DIR, backupId);\n\n // Get git info\n const gitSha = safeExec('git rev-parse HEAD', rootDir) ?? 'unknown';\n const gitBranch = safeExec('git rev-parse --abbrev-ref HEAD', rootDir) ?? 'unknown';\n\n // Collect all dead files across packages\n const allDeadFiles: DeadCodeResult['packages'][0]['deadFiles'] = [];\n for (const pkg of scanResult.packages) {\n allDeadFiles.push(...pkg.deadFiles);\n }\n\n if (allDeadFiles.length === 0) {\n return {\n backupId,\n backupPath,\n filesRemoved: 0,\n bytesRemoved: 0,\n emptyDirsRemoved: 0,\n exportsCleanedUp: 0,\n manifest: {\n id: backupId,\n createdAt: new Date().toISOString(),\n gitSha,\n gitBranch,\n removedFiles: [],\n removedEmptyDirs: [],\n cleanedExports: [],\n totalFilesRemoved: 0,\n totalBytesRemoved: 0,\n },\n };\n }\n\n // Build manifest\n const manifest: DeadCodeBackupManifest = {\n id: backupId,\n createdAt: new Date().toISOString(),\n gitSha,\n gitBranch,\n removedFiles: allDeadFiles.map(f => ({\n originalPath: f.absolutePath,\n backupPath: path.relative(rootDir, f.absolutePath),\n packageName: f.packageName,\n sizeBytes: f.sizeBytes,\n })),\n removedEmptyDirs: [],\n cleanedExports: [],\n totalFilesRemoved: allDeadFiles.length,\n totalBytesRemoved: allDeadFiles.reduce((sum, f) => sum + f.sizeBytes, 0),\n };\n\n if (dryRun) {\n return {\n backupId,\n backupPath,\n filesRemoved: allDeadFiles.length,\n bytesRemoved: manifest.totalBytesRemoved,\n emptyDirsRemoved: scanResult.summary.emptyDirectories.length,\n exportsCleanedUp: 0,\n manifest,\n };\n }\n\n // 1. Create backup directory and copy files\n const filesDir = path.join(backupPath, 'files');\n for (const deadFile of allDeadFiles) {\n const relPath = path.relative(rootDir, deadFile.absolutePath);\n const destPath = path.join(filesDir, relPath);\n const destDir = path.dirname(destPath);\n\n fs.mkdirSync(destDir, { recursive: true });\n fs.copyFileSync(deadFile.absolutePath, destPath);\n }\n\n // 2. Write manifest\n fs.writeFileSync(\n path.join(backupPath, 'manifest.json'),\n JSON.stringify(manifest, null, 2) + '\\n',\n );\n\n // 3. Delete dead files\n for (const deadFile of allDeadFiles) {\n fs.unlinkSync(deadFile.absolutePath);\n }\n\n // 4. Remove empty directories (bottom-up)\n const removedDirs: string[] = [];\n const deadFileDirs = new Set(allDeadFiles.map(f => path.dirname(f.absolutePath)));\n for (const dir of deadFileDirs) {\n removeEmptyDirsUpward(dir, rootDir, removedDirs);\n }\n manifest.removedEmptyDirs = removedDirs.map(d => path.relative(rootDir, d));\n\n // 5. Clean package.json exports\n const deletedPaths = new Set(allDeadFiles.map(f => f.absolutePath));\n let exportsCleanedUp = 0;\n for (const pkg of scanResult.packages) {\n if (pkg.deadFiles.length === 0) {continue;}\n const pkgJsonPath = path.join(pkg.packageDir, 'package.json');\n const cleaned = cleanPackageJsonExports(pkgJsonPath, deletedPaths, pkg.packageDir);\n if (cleaned.length > 0) {\n manifest.cleanedExports.push({\n packageJsonPath: path.relative(rootDir, pkgJsonPath),\n removedExportKeys: cleaned,\n });\n exportsCleanedUp += cleaned.length;\n }\n }\n\n // 6. Re-write manifest with updated empty dirs and exports info\n fs.writeFileSync(\n path.join(backupPath, 'manifest.json'),\n JSON.stringify(manifest, null, 2) + '\\n',\n );\n\n return {\n backupId,\n backupPath,\n filesRemoved: allDeadFiles.length,\n bytesRemoved: manifest.totalBytesRemoved,\n emptyDirsRemoved: removedDirs.length,\n exportsCleanedUp,\n manifest,\n };\n}\n\n/**\n * Restore files from a backup.\n */\nexport async function restoreFromBackup(\n rootDir: string,\n backupId: string,\n): Promise<{ restoredFiles: number; restoredExports: number }> {\n const backupPath = path.join(rootDir, BACKUP_DIR, backupId);\n const manifestPath = path.join(backupPath, 'manifest.json');\n\n if (!fs.existsSync(manifestPath)) {\n throw new Error(`Backup not found: ${backupId}`);\n }\n\n const manifest: DeadCodeBackupManifest = JSON.parse(\n fs.readFileSync(manifestPath, 'utf-8'),\n );\n\n let restoredFiles = 0;\n\n // Restore files\n for (const entry of manifest.removedFiles) {\n const backupFilePath = path.join(backupPath, 'files', entry.backupPath);\n if (!fs.existsSync(backupFilePath)) {continue;}\n\n // Ensure parent directory exists\n const parentDir = path.dirname(entry.originalPath);\n fs.mkdirSync(parentDir, { recursive: true });\n\n fs.copyFileSync(backupFilePath, entry.originalPath);\n restoredFiles++;\n }\n\n // Restore package.json exports\n let restoredExports = 0;\n for (const exportEntry of manifest.cleanedExports) {\n const pkgJsonPath = path.resolve(rootDir, exportEntry.packageJsonPath);\n if (!fs.existsSync(pkgJsonPath)) {continue;}\n\n // We can't perfectly restore exports without knowing the original values.\n // The safest approach: log a warning, user should rebuild.\n restoredExports += exportEntry.removedExportKeys.length;\n }\n\n return { restoredFiles, restoredExports };\n}\n\n/**\n * List all available backups.\n */\nexport function listBackups(rootDir: string): DeadCodeBackupManifest[] {\n const backupDir = path.join(rootDir, BACKUP_DIR);\n if (!fs.existsSync(backupDir)) {return [];}\n\n const backups: DeadCodeBackupManifest[] = [];\n const entries = fs.readdirSync(backupDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (!entry.isDirectory()) {continue;}\n\n const manifestPath = path.join(backupDir, entry.name, 'manifest.json');\n if (!fs.existsSync(manifestPath)) {continue;}\n\n try {\n const manifest: DeadCodeBackupManifest = JSON.parse(\n fs.readFileSync(manifestPath, 'utf-8'),\n );\n backups.push(manifest);\n } catch {\n // Skip invalid backup directories\n }\n }\n\n // Sort by date, newest first\n backups.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n\n return backups;\n}\n\n// --- Internal helpers ---\n\nfunction safeExec(cmd: string, cwd: string): string | null {\n try {\n return execSync(cmd, { cwd, encoding: 'utf-8', timeout: 5000 }).trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Walk upward from a directory, removing empty dirs until we hit\n * a non-empty one or the root boundary.\n */\nfunction removeEmptyDirsUpward(\n dir: string,\n rootBoundary: string,\n removed: string[],\n): void {\n let current = dir;\n\n while (current !== rootBoundary && current.startsWith(rootBoundary)) {\n try {\n const entries = fs.readdirSync(current);\n if (entries.length > 0) {break;} // Not empty\n\n fs.rmdirSync(current);\n removed.push(current);\n current = path.dirname(current);\n } catch {\n break;\n }\n }\n}\n\n/**\n * Remove exports from package.json that reference deleted files.\n * Returns the list of removed export keys.\n */\nfunction cleanPackageJsonExports(\n packageJsonPath: string,\n deletedPaths: Set<string>,\n packageDir: string,\n): string[] {\n if (!fs.existsSync(packageJsonPath)) {return [];}\n\n try {\n const content = fs.readFileSync(packageJsonPath, 'utf-8');\n const pkgJson = JSON.parse(content);\n const removedKeys: string[] = [];\n\n if (!pkgJson.exports || typeof pkgJson.exports !== 'object') {return [];}\n\n for (const [key, value] of Object.entries(pkgJson.exports)) {\n // Skip wildcard exports\n if (key.includes('*')) {continue;}\n\n const exportPath = extractExportImportPath(value);\n if (!exportPath) {continue;}\n\n // Map dist path to src path\n const srcPath = distToSrcForExportCheck(exportPath, packageDir);\n if (srcPath && deletedPaths.has(srcPath)) {\n delete pkgJson.exports[key];\n removedKeys.push(key);\n }\n }\n\n if (removedKeys.length > 0) {\n fs.writeFileSync(packageJsonPath, JSON.stringify(pkgJson, null, 2) + '\\n');\n }\n\n return removedKeys;\n } catch {\n return [];\n }\n}\n\nfunction extractExportImportPath(value: unknown): string | null {\n if (typeof value === 'string') {return value;}\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n for (const key of ['import', 'default', 'require']) {\n if (typeof obj[key] === 'string') {return obj[key] as string;}\n }\n }\n return null;\n}\n\nfunction distToSrcForExportCheck(\n distPath: string,\n packageDir: string,\n): string | null {\n let normalized = distPath.replace(/^\\.?\\/?/, '');\n\n if (!normalized.startsWith('dist/') && !normalized.startsWith('dist\\\\')) {\n return null;\n }\n\n normalized = 'src/' + normalized.slice(5);\n normalized = normalized\n .replace(/\\.d\\.ts$/, '.ts')\n .replace(/\\.js$/, '.ts')\n .replace(/\\.mjs$/, '.ts')\n .replace(/\\.cjs$/, '.ts');\n\n return path.resolve(packageDir, normalized);\n}\n"]}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Analyze dependencies in monorepo
3
+ *
4
+ * Atomic functions for finding duplicates, unused, and missing dependencies.
5
+ */
6
+ interface DependencyAnalysis {
7
+ duplicates: DuplicateDependency[];
8
+ unused: UnusedDependency[];
9
+ missing: MissingDependency[];
10
+ }
11
+ interface DuplicateDependency {
12
+ name: string;
13
+ versions: VersionInfo[];
14
+ totalPackages: number;
15
+ }
16
+ interface VersionInfo {
17
+ version: string;
18
+ packages: string[];
19
+ count: number;
20
+ }
21
+ interface UnusedDependency {
22
+ name: string;
23
+ packages: string[];
24
+ }
25
+ interface MissingDependency {
26
+ name: string;
27
+ packages: string[];
28
+ importedIn: string[];
29
+ }
30
+ /**
31
+ * Find duplicate dependencies with different versions
32
+ */
33
+ declare function analyzeDuplicateDependencies(rootDir: string): Promise<DuplicateDependency[]>;
34
+ /**
35
+ * Find unused dependencies (declared but not imported)
36
+ *
37
+ * Simple heuristic: check if dependency name appears in any source file
38
+ */
39
+ declare function analyzeUnusedDependencies(rootDir: string): Promise<UnusedDependency[]>;
40
+ /**
41
+ * Find missing workspace dependencies
42
+ * (imports from workspace packages not declared in dependencies)
43
+ */
44
+ declare function analyzeMissingDependencies(rootDir: string): Promise<MissingDependency[]>;
45
+ /**
46
+ * Run all dependency analysis
47
+ */
48
+ declare function analyzeDependencies(rootDir: string): Promise<DependencyAnalysis>;
49
+
50
+ export { type DependencyAnalysis, type DuplicateDependency, type MissingDependency, type UnusedDependency, type VersionInfo, analyzeDependencies, analyzeDuplicateDependencies, analyzeMissingDependencies, analyzeUnusedDependencies };
@@ -0,0 +1,200 @@
1
+ import { readFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import globby from 'globby';
4
+
5
+ // src/dependencies/analyze-deps.ts
6
+ async function analyzeDuplicateDependencies(rootDir) {
7
+ const packageJsonFiles = await globby("**/package.json", {
8
+ cwd: rootDir,
9
+ ignore: ["**/node_modules/**", "**/.git/**"],
10
+ absolute: true
11
+ });
12
+ const depVersionMap = /* @__PURE__ */ new Map();
13
+ for (const file of packageJsonFiles) {
14
+ try {
15
+ const content = await readFile(file, "utf-8");
16
+ const pkg = JSON.parse(content);
17
+ const pkgName = pkg.name || file;
18
+ const allDeps = {
19
+ ...pkg.dependencies,
20
+ ...pkg.devDependencies
21
+ };
22
+ for (const [name, version] of Object.entries(allDeps)) {
23
+ if (typeof version !== "string") {
24
+ continue;
25
+ }
26
+ if (!depVersionMap.has(name)) {
27
+ depVersionMap.set(name, /* @__PURE__ */ new Map());
28
+ }
29
+ const versionMap = depVersionMap.get(name);
30
+ if (!versionMap.has(version)) {
31
+ versionMap.set(version, []);
32
+ }
33
+ versionMap.get(version).push(pkgName);
34
+ }
35
+ } catch {
36
+ }
37
+ }
38
+ const duplicates = [];
39
+ for (const [name, versionMap] of depVersionMap) {
40
+ if (versionMap.size <= 1) {
41
+ continue;
42
+ }
43
+ const versions = Array.from(versionMap.entries()).map(
44
+ ([version, packages]) => ({
45
+ version,
46
+ packages,
47
+ count: packages.length
48
+ })
49
+ );
50
+ versions.sort((a, b) => b.count - a.count);
51
+ const totalPackages = versions.reduce((sum, v) => sum + v.count, 0);
52
+ duplicates.push({
53
+ name,
54
+ versions,
55
+ totalPackages
56
+ });
57
+ }
58
+ duplicates.sort((a, b) => b.totalPackages - a.totalPackages);
59
+ return duplicates;
60
+ }
61
+ async function analyzeUnusedDependencies(rootDir) {
62
+ const packageJsonFiles = await globby("**/package.json", {
63
+ cwd: rootDir,
64
+ ignore: ["**/node_modules/**", "**/.git/**"],
65
+ absolute: true
66
+ });
67
+ const unused = [];
68
+ for (const pkgPath of packageJsonFiles) {
69
+ try {
70
+ const content = await readFile(pkgPath, "utf-8");
71
+ const pkg = JSON.parse(content);
72
+ const pkgName = pkg.name || pkgPath;
73
+ const pkgDir = join(pkgPath, "..");
74
+ const allDeps = {
75
+ ...pkg.dependencies,
76
+ ...pkg.devDependencies
77
+ };
78
+ const sourceFiles = await globby("src/**/*.{ts,tsx,js,jsx}", {
79
+ cwd: pkgDir,
80
+ absolute: true,
81
+ ignore: ["**/*.test.*", "**/*.spec.*"]
82
+ });
83
+ const sourceContents = await Promise.all(
84
+ sourceFiles.map(async (file) => {
85
+ try {
86
+ return readFile(file, "utf-8");
87
+ } catch {
88
+ return "";
89
+ }
90
+ })
91
+ );
92
+ const allSource = sourceContents.join("\n");
93
+ for (const depName of Object.keys(allDeps)) {
94
+ if (depName.startsWith("@types/") || depName === "typescript" || depName === "tsup" || depName === "vitest" || depName === "eslint" || depName === "prettier") {
95
+ continue;
96
+ }
97
+ if (!allSource.includes(depName)) {
98
+ const existing = unused.find((u) => u.name === depName);
99
+ if (existing) {
100
+ existing.packages.push(pkgName);
101
+ } else {
102
+ unused.push({
103
+ name: depName,
104
+ packages: [pkgName]
105
+ });
106
+ }
107
+ }
108
+ }
109
+ } catch {
110
+ }
111
+ }
112
+ return unused;
113
+ }
114
+ async function analyzeMissingDependencies(rootDir) {
115
+ const packageJsonFiles = await globby("**/package.json", {
116
+ cwd: rootDir,
117
+ ignore: ["**/node_modules/**", "**/.git/**"],
118
+ absolute: true
119
+ });
120
+ const workspacePackages = /* @__PURE__ */ new Set();
121
+ for (const file of packageJsonFiles) {
122
+ try {
123
+ const content = await readFile(file, "utf-8");
124
+ const pkg = JSON.parse(content);
125
+ if (pkg.name) {
126
+ workspacePackages.add(pkg.name);
127
+ }
128
+ } catch {
129
+ }
130
+ }
131
+ const missing = [];
132
+ for (const pkgPath of packageJsonFiles) {
133
+ try {
134
+ const content = await readFile(pkgPath, "utf-8");
135
+ const pkg = JSON.parse(content);
136
+ if (!pkg.name) {
137
+ continue;
138
+ }
139
+ const pkgName = pkg.name;
140
+ const pkgDir = join(pkgPath, "..");
141
+ const declaredDeps = /* @__PURE__ */ new Set([
142
+ ...Object.keys(pkg.dependencies || {}),
143
+ ...Object.keys(pkg.devDependencies || {})
144
+ ]);
145
+ const sourceFiles = await globby("src/**/*.{ts,tsx,js,jsx}", {
146
+ cwd: pkgDir,
147
+ absolute: true
148
+ });
149
+ for (const file of sourceFiles) {
150
+ try {
151
+ const source = await readFile(file, "utf-8");
152
+ const importRegex = /from\s+['"](@[\w-]+\/[\w-]+|[\w-]+)['"]/g;
153
+ let match;
154
+ while ((match = importRegex.exec(source)) !== null) {
155
+ const importedPkg = match[1];
156
+ if (!importedPkg) {
157
+ continue;
158
+ }
159
+ if (workspacePackages.has(importedPkg) && !declaredDeps.has(importedPkg)) {
160
+ const existing = missing.find((m) => m.name === importedPkg);
161
+ if (existing) {
162
+ if (!existing.packages.includes(pkgName)) {
163
+ existing.packages.push(pkgName);
164
+ }
165
+ if (!existing.importedIn.includes(file)) {
166
+ existing.importedIn.push(file);
167
+ }
168
+ } else {
169
+ missing.push({
170
+ name: importedPkg,
171
+ packages: [pkgName],
172
+ importedIn: [file]
173
+ });
174
+ }
175
+ }
176
+ }
177
+ } catch {
178
+ }
179
+ }
180
+ } catch {
181
+ }
182
+ }
183
+ return missing;
184
+ }
185
+ async function analyzeDependencies(rootDir) {
186
+ const [duplicates, unused, missing] = await Promise.all([
187
+ analyzeDuplicateDependencies(rootDir),
188
+ analyzeUnusedDependencies(rootDir),
189
+ analyzeMissingDependencies(rootDir)
190
+ ]);
191
+ return {
192
+ duplicates,
193
+ unused,
194
+ missing
195
+ };
196
+ }
197
+
198
+ export { analyzeDependencies, analyzeDuplicateDependencies, analyzeMissingDependencies, analyzeUnusedDependencies };
199
+ //# sourceMappingURL=index.js.map
200
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/dependencies/analyze-deps.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Analyze dependencies in monorepo\n *\n * Atomic functions for finding duplicates, unused, and missing dependencies.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport globby from 'globby';\n\nexport interface DependencyAnalysis {\n duplicates: DuplicateDependency[];\n unused: UnusedDependency[];\n missing: MissingDependency[];\n}\n\nexport interface DuplicateDependency {\n name: string;\n versions: VersionInfo[];\n totalPackages: number;\n}\n\nexport interface VersionInfo {\n version: string;\n packages: string[];\n count: number;\n}\n\nexport interface UnusedDependency {\n name: string;\n packages: string[];\n}\n\nexport interface MissingDependency {\n name: string;\n packages: string[];\n importedIn: string[];\n}\n\n/**\n * Find duplicate dependencies with different versions\n */\nexport async function analyzeDuplicateDependencies(\n rootDir: string\n): Promise<DuplicateDependency[]> {\n const packageJsonFiles = await globby('**/package.json', {\n cwd: rootDir,\n ignore: ['**/node_modules/**', '**/.git/**'],\n absolute: true,\n });\n\n // Map: depName -> Map: version -> packages[]\n const depVersionMap = new Map<string, Map<string, string[]>>();\n\n for (const file of packageJsonFiles) {\n try {\n const content = await readFile(file, 'utf-8');\n const pkg = JSON.parse(content);\n const pkgName = pkg.name || file;\n\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n for (const [name, version] of Object.entries(allDeps)) {\n if (typeof version !== 'string') {continue;}\n\n if (!depVersionMap.has(name)) {\n depVersionMap.set(name, new Map());\n }\n\n const versionMap = depVersionMap.get(name)!;\n if (!versionMap.has(version)) {\n versionMap.set(version, []);\n }\n\n versionMap.get(version)!.push(pkgName);\n }\n } catch {\n // Skip invalid package.json\n }\n }\n\n // Find duplicates (more than 1 version)\n const duplicates: DuplicateDependency[] = [];\n\n for (const [name, versionMap] of depVersionMap) {\n if (versionMap.size <= 1) {continue;}\n\n const versions: VersionInfo[] = Array.from(versionMap.entries()).map(\n ([version, packages]) => ({\n version,\n packages,\n count: packages.length,\n })\n );\n\n // Sort by count descending\n versions.sort((a, b) => b.count - a.count);\n\n const totalPackages = versions.reduce((sum, v) => sum + v.count, 0);\n\n duplicates.push({\n name,\n versions,\n totalPackages,\n });\n }\n\n // Sort by total packages descending\n duplicates.sort((a, b) => b.totalPackages - a.totalPackages);\n\n return duplicates;\n}\n\n/**\n * Find unused dependencies (declared but not imported)\n *\n * Simple heuristic: check if dependency name appears in any source file\n */\nexport async function analyzeUnusedDependencies(\n rootDir: string\n): Promise<UnusedDependency[]> {\n const packageJsonFiles = await globby('**/package.json', {\n cwd: rootDir,\n ignore: ['**/node_modules/**', '**/.git/**'],\n absolute: true,\n });\n\n const unused: UnusedDependency[] = [];\n\n for (const pkgPath of packageJsonFiles) {\n try {\n const content = await readFile(pkgPath, 'utf-8');\n const pkg = JSON.parse(content);\n const pkgName = pkg.name || pkgPath;\n const pkgDir = join(pkgPath, '..');\n\n // Get all dependencies\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n // Get all source files in this package\n const sourceFiles = await globby('src/**/*.{ts,tsx,js,jsx}', {\n cwd: pkgDir,\n absolute: true,\n ignore: ['**/*.test.*', '**/*.spec.*'],\n });\n\n // Read all source content\n const sourceContents = await Promise.all(\n sourceFiles.map(async (file: string) => {\n try {\n return readFile(file, 'utf-8');\n } catch {\n return '';\n }\n })\n );\n\n const allSource = sourceContents.join('\\n');\n\n // Check each dependency\n for (const depName of Object.keys(allDeps)) {\n // Skip build tools and type packages (likely used in config files)\n if (\n depName.startsWith('@types/') ||\n depName === 'typescript' ||\n depName === 'tsup' ||\n depName === 'vitest' ||\n depName === 'eslint' ||\n depName === 'prettier'\n ) {\n continue;\n }\n\n // Simple check: does the dep name appear in source?\n if (!allSource.includes(depName)) {\n // Check if it's already in unused array\n const existing = unused.find((u) => u.name === depName);\n if (existing) {\n existing.packages.push(pkgName);\n } else {\n unused.push({\n name: depName,\n packages: [pkgName],\n });\n }\n }\n }\n } catch {\n // Skip invalid package.json\n }\n }\n\n return unused;\n}\n\n/**\n * Find missing workspace dependencies\n * (imports from workspace packages not declared in dependencies)\n */\nexport async function analyzeMissingDependencies(\n rootDir: string\n): Promise<MissingDependency[]> {\n // Get all workspace package names\n const packageJsonFiles = await globby('**/package.json', {\n cwd: rootDir,\n ignore: ['**/node_modules/**', '**/.git/**'],\n absolute: true,\n });\n\n const workspacePackages = new Set<string>();\n\n for (const file of packageJsonFiles) {\n try {\n const content = await readFile(file, 'utf-8');\n const pkg = JSON.parse(content);\n if (pkg.name) {\n workspacePackages.add(pkg.name);\n }\n } catch {\n // Skip\n }\n }\n\n const missing: MissingDependency[] = [];\n\n // Check each package\n for (const pkgPath of packageJsonFiles) {\n try {\n const content = await readFile(pkgPath, 'utf-8');\n const pkg = JSON.parse(content);\n\n if (!pkg.name) {\n continue; // Skip packages without name\n }\n\n const pkgName = pkg.name;\n const pkgDir = join(pkgPath, '..');\n\n const declaredDeps = new Set([\n ...Object.keys(pkg.dependencies || {}),\n ...Object.keys(pkg.devDependencies || {}),\n ]);\n\n // Get all source files\n const sourceFiles = await globby('src/**/*.{ts,tsx,js,jsx}', {\n cwd: pkgDir,\n absolute: true,\n });\n\n // Check imports in each file\n for (const file of sourceFiles) {\n try {\n const source = await readFile(file, 'utf-8');\n\n // Simple regex to find imports\n const importRegex = /from\\s+['\"](@[\\w-]+\\/[\\w-]+|[\\w-]+)['\"]/g;\n let match;\n\n while ((match = importRegex.exec(source)) !== null) {\n const importedPkg = match[1];\n\n if (!importedPkg) {\n continue;\n }\n\n // Check if it's a workspace package\n if (\n workspacePackages.has(importedPkg) &&\n !declaredDeps.has(importedPkg)\n ) {\n const existing = missing.find((m) => m.name === importedPkg);\n if (existing) {\n if (!existing.packages.includes(pkgName)) {\n existing.packages.push(pkgName);\n }\n if (!existing.importedIn.includes(file)) {\n existing.importedIn.push(file);\n }\n } else {\n missing.push({\n name: importedPkg,\n packages: [pkgName],\n importedIn: [file],\n });\n }\n }\n }\n } catch {\n // Skip file\n }\n }\n } catch {\n // Skip package\n }\n }\n\n return missing;\n}\n\n/**\n * Run all dependency analysis\n */\nexport async function analyzeDependencies(\n rootDir: string\n): Promise<DependencyAnalysis> {\n const [duplicates, unused, missing] = await Promise.all([\n analyzeDuplicateDependencies(rootDir),\n analyzeUnusedDependencies(rootDir),\n analyzeMissingDependencies(rootDir),\n ]);\n\n return {\n duplicates,\n unused,\n missing,\n };\n}\n"]}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Dependency graph utilities for monorepo analysis
3
+ *
4
+ * Provides topological sorting, circular dependency detection,
5
+ * and build order calculation based on workspace dependencies.
6
+ */
7
+ interface PackageNode {
8
+ name: string;
9
+ path: string;
10
+ dir: string;
11
+ deps: Set<string>;
12
+ devDeps?: Set<string>;
13
+ dependents: Set<string>;
14
+ }
15
+ interface DependencyGraph {
16
+ nodes: Map<string, PackageNode>;
17
+ workspacePackages: Set<string>;
18
+ }
19
+ interface TopologicalSortResult {
20
+ layers: string[][];
21
+ sorted: string[];
22
+ circular: string[][];
23
+ }
24
+ /**
25
+ * Build dependency graph from monorepo packages
26
+ */
27
+ declare function buildDependencyGraph(rootDir: string): DependencyGraph;
28
+ /**
29
+ * Topological sort using Kahn's algorithm
30
+ * Returns build layers where each layer can be built in parallel
31
+ */
32
+ declare function topologicalSort(graph: DependencyGraph): TopologicalSortResult;
33
+ /**
34
+ * Find circular dependencies using DFS
35
+ */
36
+ declare function findCircularDependencies(graph: DependencyGraph, subset?: Set<string>): string[][];
37
+ /**
38
+ * Get build order for a specific package and its dependencies
39
+ */
40
+ declare function getBuildOrderForPackage(graph: DependencyGraph, packageName: string): TopologicalSortResult;
41
+ /**
42
+ * Reverse dependency graph - who depends on this package
43
+ */
44
+ declare function getReverseDependencies(graph: DependencyGraph, packageName: string): Set<string>;
45
+ /**
46
+ * Get impact analysis - all packages affected by changes to this package
47
+ */
48
+ declare function getImpactAnalysis(graph: DependencyGraph, packageName: string): Set<string>;
49
+
50
+ export { type DependencyGraph, type PackageNode, type TopologicalSortResult, buildDependencyGraph, findCircularDependencies, getBuildOrderForPackage, getImpactAnalysis, getReverseDependencies, topologicalSort };