@kb-labs/quality-core 2.119.0-canary.f8394d5fd → 2.119.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.
- package/dist/builds/index.js.map +1 -1
- package/dist/dead-code/index.js.map +1 -1
- package/dist/dependencies/index.js.map +1 -1
- package/dist/graph/index.js.map +1 -1
- package/dist/health/index.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/stale/index.js.map +1 -1
- package/dist/stats/index.js.map +1 -1
- package/dist/tests/index.js.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +5 -5
package/dist/builds/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../../../home/runner/work/kb-labs/kb-labs/plugins/quality/core/src/builds/check-builds.ts"],"names":[],"mappings":";;;;;;AAWA,IAAM,SAAA,GAAY,UAAU,IAAI,CAAA;AA4BhC,SAAS,2BAAA,CAA4B,SAAiB,MAAA,EAA2B;AAC/E,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,OAAO,CAAA,EAAG;AAC3B,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAU,EAAA,CAAG,WAAA,CAAY,SAAS,EAAE,aAAA,EAAe,MAAM,CAAA;AAE/D,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,IAAA,IAAI,CAAC,MAAM,WAAA,EAAY,IAAK,CAAC,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,UAAU,CAAA,EAAG;AAAC,MAAA;AAAA,IAAS;AAE1E,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,MAAM,IAAI,CAAA;AAC9C,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,UAAU,CAAA;AAElD,IAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,WAAW,CAAA,EAAG;AAAC,MAAA;AAAA,IAAS;AAE3C,IAAA,MAAM,cAAc,EAAA,CAAG,WAAA,CAAY,aAAa,EAAE,aAAA,EAAe,MAAM,CAAA;AAEvE,IAAA,KAAA,MAAW,UAAU,WAAA,EAAa;AAChC,MAAA,IAAI,CAAC,MAAA,CAAO,WAAA,EAAY,EAAG;AAAC,QAAA;AAAA,MAAS;AAErC,MAAA,MAAM,kBAAkB,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa,MAAA,CAAO,MAAM,cAAc,CAAA;AAE1E,MAAA,IAAI,EAAA,CAAG,UAAA,CAAW,eAAe,CAAA,EAAG;AAClC,QAAA,MAAM,UAAU,IAAA,CAAK,KAAA,CAAM,GAAG,YAAA,CAAa,eAAA,EAAiB,OAAO,CAAC,CAAA;AAGpE,QAAA,IAAI,CAAC,OAAA,CAAQ,OAAA,EAAS,KAAA,EAAO;AAAC,UAAA;AAAA,QAAS;AAGvC,QAAA,IAAI,MAAA,IAAU,CAAC,OAAA,CAAQ,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,IAAK,CAAC,MAAA,CAAO,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC7E,UAAA;AAAA,QACF;AAEA,QAAA,QAAA,CAAS,KAAK,eAAe,CAAA;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;AAKA,SAAS,YAAY,UAAA,EAInB;AACA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,UAAA,EAAY,eAAe,CAAA;AACtD,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,IAAA,CAAK,UAAA,EAAY,KAAK,CAAA;AAE1C,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC5B,IAAA,OAAO,EAAE,OAAO,KAAA,EAAM;AAAA,EACxB;AAEA,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,MAAM,CAAA,EAAG;AAC1B,IAAA,OAAO,EAAE,OAAO,KAAA,EAAM;AAAA,EACxB;AAEA,EAAA,MAAM,YAAY,EAAA,CAAG,QAAA,CAAS,QAAQ,CAAA,CAAE,MAAM,OAAA,EAAQ;AAGtD,EAAA,IAAI,cAAA,GAAiB,CAAA;AAErB,EAAA,SAAS,QAAQ,GAAA,EAAa;AAC5B,IAAA,MAAM,UAAU,EAAA,CAAG,WAAA,CAAY,KAAK,EAAE,aAAA,EAAe,MAAM,CAAA;AAC3D,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,MAAM,IAAI,CAAA;AAC1C,MAAA,IAAI,KAAA,CAAM,aAAY,EAAG;AACvB,QAAA,OAAA,CAAQ,QAAQ,CAAA;AAAA,MAClB,CAAA,MAAA,IAAW,oBAAA,CAAqB,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AAChD,QAAA,MAAM,QAAQ,EAAA,CAAG,QAAA,CAAS,QAAQ,CAAA,CAAE,MAAM,OAAA,EAAQ;AAClD,QAAA,IAAI,QAAQ,cAAA,EAAgB;AAC1B,UAAA,cAAA,GAAiB,KAAA;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,MAAM,CAAA;AAEd,EAAA,OAAO;AAAA,IACL,OAAO,cAAA,GAAiB,SAAA;AAAA,IACxB,SAAA;AAAA,IACA,QAAA,EAAU;AAAA,GACZ;AACF;AAKA,eAAe,eAAA,CACb,UAAA,EACA,WAAA,EACA,OAAA,EACkE;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,UAAU,gBAAA,EAAkB;AAAA,MAChC,GAAA,EAAK,UAAA;AAAA,MACL,OAAA;AAAA,MACA,QAAA,EAAU;AAAA,KACX,CAAA;AAED,IAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AAAA,EACzB,SAAS,GAAA,EAAc;AACrB,IAAA,MAAM,QAAA,GAAW,GAAA;AACjB,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,KAAA,EAAO,SAAS,MAAA,EAAQ,IAAA,MAAU,QAAA,CAAS,OAAA,IAAW,OAAO,GAAG,CAAA;AAAA,MAChE,QAAA,EAAU,SAAS,IAAA,IAAQ;AAAA,KAC7B;AAAA,EACF;AACF;AAOA,eAAsB,WAAA,CACpB,OAAA,EACA,OAAA,GAA6B,EAAC,EACH;AAC3B,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,GAAA;AAEnC,EAAA,MAAM,YAAA,GAAe,2BAAA,CAA4B,OAAA,EAAS,OAAA,CAAQ,aAAa,CAAA;AAE/E,EAAA,MAAM,MAAA,GAA2B;AAAA,IAC/B,eAAe,YAAA,CAAa,MAAA;AAAA,IAC5B,OAAA,EAAS,CAAA;AAAA,IACT,OAAA,EAAS,CAAA;AAAA,IACT,UAAU,EAAC;AAAA,IACX,aAAa,EAAC;AAAA,IACd,QAAA,EAAU;AAAA,GACZ;AAGA,EAAA,KAAA,MAAW,WAAW,YAAA,EAAc;AAClC,IAAA,MAAM,UAAU,IAAA,CAAK,KAAA,CAAM,GAAG,YAAA,CAAa,OAAA,EAAS,OAAO,CAAC,CAAA;AAC5D,IAAA,MAAM,cAAc,OAAA,CAAQ,IAAA;AAC5B,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA;AAGvC,IAAA,MAAM,UAAA,GAAa,YAAY,UAAU,CAAA;AACzC,IAAA,IAAI,WAAW,KAAA,EAAO;AACpB,MAAA,MAAA,CAAO,YAAY,IAAA,CAAK;AAAA,QACtB,OAAA,EAAS,WAAA;AAAA,QACT,WAAW,UAAA,CAAW,SAAA;AAAA,QACtB,UAAU,UAAA,CAAW;AAAA,OACtB,CAAA;AAAA,IACH;AAGA,IAAA,MAAM,WAAA,GAAc,MAAM,eAAA,CAAgB,UAAA,EAAY,aAAa,OAAO,CAAA;AAE1E,IAAA,IAAI,YAAY,OAAA,EAAS;AACvB,MAAA,MAAA,CAAO,OAAA,EAAA;AAAA,IACT,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,OAAA,EAAA;AACP,MAAA,MAAA,CAAO,SAAS,IAAA,CAAK;AAAA,QACnB,OAAA,EAAS,WAAA;AAAA,QACT,OAAO,WAAA,CAAY,KAAA;AAAA,QACnB,UAAU,WAAA,CAAY;AAAA,OACvB,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,MAAA,CAAO,QAAA,GAAW,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAE/B,EAAA,OAAO,MAAA;AACT","file":"index.js","sourcesContent":["/**\n * Check build status across monorepo packages\n *\n * Pure computation - no CLI, no dependencies on devkit\n */\n\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nconst execAsync = promisify(exec);\n\nexport interface BuildCheckResult {\n totalPackages: number;\n passing: number;\n failing: number;\n failures: Array<{\n package: string;\n error: string;\n exitCode: number;\n }>;\n staleBuilds: Array<{\n package: string;\n distMtime: number;\n srcMtime: number;\n }>;\n duration: number;\n}\n\nexport interface BuildCheckOptions {\n packageFilter?: string;\n includeDevDeps?: boolean;\n timeout?: number; // per-package timeout in ms\n}\n\n/**\n * Find all packages with build scripts\n */\nfunction findPackagesWithBuildScript(rootDir: string, filter?: string): string[] {\n const packages: string[] = [];\n\n if (!fs.existsSync(rootDir)) {\n return packages;\n }\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\n if (fs.existsSync(packageJsonPath)) {\n const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n\n // Skip if no build script\n if (!pkgJson.scripts?.build) {continue;}\n\n // Skip if filter doesn't match\n if (filter && !pkgJson.name.includes(filter) && !pkgDir.name.includes(filter)) {\n continue;\n }\n\n packages.push(packageJsonPath);\n }\n }\n }\n\n return packages;\n}\n\n/**\n * Check if dist/ is stale (older than src/)\n */\nfunction isDistStale(packageDir: string): {\n stale: boolean;\n distMtime?: number;\n srcMtime?: number;\n} {\n const distFile = path.join(packageDir, 'dist/index.js');\n const srcDir = path.join(packageDir, 'src');\n\n if (!fs.existsSync(distFile)) {\n return { stale: false };\n }\n\n if (!fs.existsSync(srcDir)) {\n return { stale: false };\n }\n\n const distMtime = fs.statSync(distFile).mtime.getTime();\n\n // Find newest file in src/\n let newestSrcMtime = 0;\n\n function walkDir(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkDir(fullPath);\n } else if (/\\.(ts|tsx|js|jsx)$/.test(entry.name)) {\n const mtime = fs.statSync(fullPath).mtime.getTime();\n if (mtime > newestSrcMtime) {\n newestSrcMtime = mtime;\n }\n }\n }\n }\n\n walkDir(srcDir);\n\n return {\n stale: newestSrcMtime > distMtime,\n distMtime,\n srcMtime: newestSrcMtime,\n };\n}\n\n/**\n * Try to build a single package\n */\nasync function tryBuildPackage(\n packageDir: string,\n packageName: string,\n timeout: number\n): Promise<{ success: boolean; error?: string; exitCode?: number }> {\n try {\n await execAsync('pnpm run build', {\n cwd: packageDir,\n timeout,\n encoding: 'utf-8',\n });\n\n return { success: true };\n } catch (err: unknown) {\n const spawnErr = err as { stderr?: string; message?: string; code?: number };\n return {\n success: false,\n error: spawnErr.stderr?.trim() || spawnErr.message || String(err),\n exitCode: spawnErr.code || 1,\n };\n }\n}\n\n/**\n * Check builds across monorepo\n *\n * @returns Build check results with failures and stale builds\n */\nexport async function checkBuilds(\n rootDir: string,\n options: BuildCheckOptions = {}\n): Promise<BuildCheckResult> {\n const startTime = Date.now();\n const timeout = options.timeout || 30000; // 30s default\n\n const packagePaths = findPackagesWithBuildScript(rootDir, options.packageFilter);\n\n const result: BuildCheckResult = {\n totalPackages: packagePaths.length,\n passing: 0,\n failing: 0,\n failures: [],\n staleBuilds: [],\n duration: 0,\n };\n\n // Check builds sequentially (parallel would be too heavy)\n for (const pkgPath of packagePaths) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));\n const packageName = pkgJson.name;\n const packageDir = path.dirname(pkgPath);\n\n // Check if dist is stale\n const staleCheck = isDistStale(packageDir);\n if (staleCheck.stale) {\n result.staleBuilds.push({\n package: packageName,\n distMtime: staleCheck.distMtime!,\n srcMtime: staleCheck.srcMtime!,\n });\n }\n\n // Try to build\n const buildResult = await tryBuildPackage(packageDir, packageName, timeout);\n\n if (buildResult.success) {\n result.passing++;\n } else {\n result.failing++;\n result.failures.push({\n package: packageName,\n error: buildResult.error!,\n exitCode: buildResult.exitCode!,\n });\n }\n }\n\n result.duration = Date.now() - startTime;\n\n return result;\n}\n"]}
|
|
@@ -1 +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/knip-runner.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 * Knip integration — runs `knip --reporter json` and parses output.\n *\n * Knip is already installed at the workspace root and configured via knip.config.ts.\n * We invoke it as a shell command and parse its JSON report.\n */\n\nimport type { ShellAPI } from '@kb-labs/sdk';\nimport type { KnipReport } from '@kb-labs/quality-contracts';\n\ninterface KnipJsonOutput {\n files?: string[];\n exports?: Array<{\n file: string;\n exports: Array<{ symbol: string }>;\n }>;\n dependencies?: Array<{\n name: string;\n packages?: string[];\n }>;\n devDependencies?: Array<{\n name: string;\n packages?: string[];\n }>;\n unlisted?: Array<{\n name: string;\n packages?: string[];\n }>;\n}\n\nexport interface RunKnipOptions {\n shell: ShellAPI;\n rootDir: string;\n}\n\n/**\n * Run knip and return parsed report.\n * Knip exits non-zero when issues are found — that is expected, not an error.\n */\nexport async function runKnip(opts: RunKnipOptions): Promise<KnipReport> {\n const { shell, rootDir } = opts;\n\n // Run knip; ignore non-zero exit code since knip exits 1 when issues are found\n const result = await shell.exec('pnpm', ['knip', '--reporter', 'json'], { cwd: rootDir }).catch(() => null);\n\n if (!result) {return emptyReport();}\n\n const raw = result.stdout.trim();\n if (!raw || raw === '{}' || raw === '[]') {return emptyReport();}\n\n let parsed: KnipJsonOutput;\n try {\n parsed = JSON.parse(raw) as KnipJsonOutput;\n } catch {\n return emptyReport();\n }\n\n return parseKnipOutput(parsed, rootDir);\n}\n\nfunction parseKnipOutput(out: KnipJsonOutput, rootDir: string): KnipReport {\n const unusedFiles: string[] = (out.files ?? []).map(f =>\n f.startsWith('/') ? f : `${rootDir}/${f}`\n );\n\n const unusedExports = (out.exports ?? []).flatMap(entry =>\n (entry.exports ?? []).map(exp => ({\n file: entry.file,\n symbol: exp.symbol,\n }))\n );\n\n const unusedDependencies = (out.dependencies ?? []).flatMap(dep =>\n (dep.packages ?? [rootDir]).map(workspace => ({\n package: dep.name,\n workspace,\n }))\n );\n\n const unlistedDependencies = (out.unlisted ?? []).flatMap(dep =>\n (dep.packages ?? [rootDir]).map(workspace => ({\n package: dep.name,\n workspace,\n }))\n );\n\n const totalIssues =\n unusedFiles.length +\n unusedExports.length +\n unusedDependencies.length +\n unlistedDependencies.length;\n\n return { unusedFiles, unusedExports, unusedDependencies, unlistedDependencies, totalIssues };\n}\n\nfunction emptyReport(): KnipReport {\n return {\n unusedFiles: [],\n unusedExports: [],\n unusedDependencies: [],\n unlistedDependencies: [],\n totalIssues: 0,\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"]}
|
|
1
|
+
{"version":3,"sources":["../../../home/runner/work/kb-labs/kb-labs/plugins/quality/core/src/dead-code/entry-points.ts","../../../home/runner/work/kb-labs/kb-labs/plugins/quality/core/src/dead-code/import-graph.ts","../../../home/runner/work/kb-labs/kb-labs/plugins/quality/core/src/dead-code/scan-dead-files.ts","../../../home/runner/work/kb-labs/kb-labs/plugins/quality/core/src/dead-code/knip-runner.ts","../../../home/runner/work/kb-labs/kb-labs/plugins/quality/core/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 * Knip integration — runs `knip --reporter json` and parses output.\n *\n * Knip is already installed at the workspace root and configured via knip.config.ts.\n * We invoke it as a shell command and parse its JSON report.\n */\n\nimport type { ShellAPI } from '@kb-labs/sdk';\nimport type { KnipReport } from '@kb-labs/quality-contracts';\n\ninterface KnipJsonOutput {\n files?: string[];\n exports?: Array<{\n file: string;\n exports: Array<{ symbol: string }>;\n }>;\n dependencies?: Array<{\n name: string;\n packages?: string[];\n }>;\n devDependencies?: Array<{\n name: string;\n packages?: string[];\n }>;\n unlisted?: Array<{\n name: string;\n packages?: string[];\n }>;\n}\n\nexport interface RunKnipOptions {\n shell: ShellAPI;\n rootDir: string;\n}\n\n/**\n * Run knip and return parsed report.\n * Knip exits non-zero when issues are found — that is expected, not an error.\n */\nexport async function runKnip(opts: RunKnipOptions): Promise<KnipReport> {\n const { shell, rootDir } = opts;\n\n // Run knip; ignore non-zero exit code since knip exits 1 when issues are found\n const result = await shell.exec('pnpm', ['knip', '--reporter', 'json'], { cwd: rootDir }).catch(() => null);\n\n if (!result) {return emptyReport();}\n\n const raw = result.stdout.trim();\n if (!raw || raw === '{}' || raw === '[]') {return emptyReport();}\n\n let parsed: KnipJsonOutput;\n try {\n parsed = JSON.parse(raw) as KnipJsonOutput;\n } catch {\n return emptyReport();\n }\n\n return parseKnipOutput(parsed, rootDir);\n}\n\nfunction parseKnipOutput(out: KnipJsonOutput, rootDir: string): KnipReport {\n const unusedFiles: string[] = (out.files ?? []).map(f =>\n f.startsWith('/') ? f : `${rootDir}/${f}`\n );\n\n const unusedExports = (out.exports ?? []).flatMap(entry =>\n (entry.exports ?? []).map(exp => ({\n file: entry.file,\n symbol: exp.symbol,\n }))\n );\n\n const unusedDependencies = (out.dependencies ?? []).flatMap(dep =>\n (dep.packages ?? [rootDir]).map(workspace => ({\n package: dep.name,\n workspace,\n }))\n );\n\n const unlistedDependencies = (out.unlisted ?? []).flatMap(dep =>\n (dep.packages ?? [rootDir]).map(workspace => ({\n package: dep.name,\n workspace,\n }))\n );\n\n const totalIssues =\n unusedFiles.length +\n unusedExports.length +\n unusedDependencies.length +\n unlistedDependencies.length;\n\n return { unusedFiles, unusedExports, unusedDependencies, unlistedDependencies, totalIssues };\n}\n\nfunction emptyReport(): KnipReport {\n return {\n unusedFiles: [],\n unusedExports: [],\n unusedDependencies: [],\n unlistedDependencies: [],\n totalIssues: 0,\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"]}
|
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"sources":["../../../home/runner/work/kb-labs/kb-labs/plugins/quality/core/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"]}
|
package/dist/graph/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/graph/dependency-graph.ts"],"names":["path"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Dependency graph utilities for monorepo analysis\n *\n * Provides topological sorting, circular dependency detection,\n * and build order calculation based on workspace dependencies.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface PackageNode {\n name: string;\n path: string;\n dir: string;\n deps: Set<string>;\n devDeps?: Set<string>;\n dependents: Set<string>; // Packages that depend on this one\n}\n\nexport interface DependencyGraph {\n nodes: Map<string, PackageNode>;\n workspacePackages: Set<string>;\n}\n\nexport interface TopologicalSortResult {\n layers: string[][]; // Build layers - each layer can build in parallel\n sorted: string[]; // Flattened topological order\n circular: string[][]; // Circular dependency chains\n}\n\n/**\n * Build dependency graph from monorepo packages\n */\nexport function buildDependencyGraph(rootDir: string): DependencyGraph {\n const nodes = new Map<string, PackageNode>();\n const workspacePackages = new Set<string>();\n\n if (!fs.existsSync(rootDir)) {\n return { nodes, workspacePackages };\n }\n\n const entries = fs.readdirSync(rootDir, { withFileTypes: true });\n\n // First pass: collect all workspace packages\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\n if (fs.existsSync(packageJsonPath)) {\n const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const packageName = pkgJson.name;\n\n if (packageName) {\n workspacePackages.add(packageName);\n }\n }\n }\n }\n\n // Second pass: build dependency graph\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\n if (fs.existsSync(packageJsonPath)) {\n const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const packageName = pkgJson.name;\n\n if (!packageName) {continue;}\n\n const deps = new Set<string>();\n const devDeps = new Set<string>();\n\n // Collect workspace dependencies\n const allDeps = {\n ...pkgJson.dependencies,\n ...pkgJson.devDependencies,\n };\n\n for (const dep of Object.keys(allDeps)) {\n if (workspacePackages.has(dep)) {\n deps.add(dep);\n }\n }\n\n // Separate dev dependencies\n if (pkgJson.devDependencies) {\n for (const dep of Object.keys(pkgJson.devDependencies)) {\n if (workspacePackages.has(dep)) {\n devDeps.add(dep);\n }\n }\n }\n\n nodes.set(packageName, {\n name: packageName,\n path: packageJsonPath,\n dir: path.dirname(packageJsonPath),\n deps,\n devDeps,\n dependents: new Set(),\n });\n }\n }\n }\n\n // Second pass: calculate reverse dependencies (dependents)\n for (const [packageName, node] of nodes) {\n for (const dep of node.deps) {\n const depNode = nodes.get(dep);\n if (depNode) {\n depNode.dependents.add(packageName);\n }\n }\n }\n\n return { nodes, workspacePackages };\n}\n\n/**\n * Topological sort using Kahn's algorithm\n * Returns build layers where each layer can be built in parallel\n */\nexport function topologicalSort(graph: DependencyGraph): TopologicalSortResult {\n const { nodes } = graph;\n const layers: string[][] = [];\n const sorted: string[] = [];\n const circular: string[][] = [];\n\n // Calculate in-degree for each node\n const inDegree = new Map<string, number>();\n for (const [name] of nodes) {\n inDegree.set(name, 0);\n }\n\n for (const [, node] of nodes) {\n for (const dep of node.deps) {\n if (nodes.has(dep)) {\n inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);\n }\n }\n }\n\n // Kahn's algorithm with layers\n const queue: string[] = [];\n for (const [name, degree] of inDegree) {\n if (degree === 0) {\n queue.push(name);\n }\n }\n\n while (queue.length > 0) {\n const layer: string[] = [...queue];\n layers.push(layer);\n sorted.push(...layer);\n queue.length = 0;\n\n for (const name of layer) {\n const node = nodes.get(name);\n if (!node) {continue;}\n\n for (const dep of node.deps) {\n if (nodes.has(dep)) {\n const newDegree = (inDegree.get(dep) ?? 0) - 1;\n inDegree.set(dep, newDegree);\n if (newDegree === 0) {\n queue.push(dep);\n }\n }\n }\n }\n }\n\n // Check for circular dependencies\n if (sorted.length < nodes.size) {\n const remaining = new Set<string>();\n for (const [name] of nodes) {\n if (!sorted.includes(name)) {\n remaining.add(name);\n }\n }\n\n // Find cycles using DFS\n const cycles = findCircularDependencies(graph, remaining);\n circular.push(...cycles);\n }\n\n return { layers, sorted, circular };\n}\n\n/**\n * Find circular dependencies using DFS\n */\nexport function findCircularDependencies(\n graph: DependencyGraph,\n subset?: Set<string>\n): string[][] {\n const { nodes } = graph;\n const visited = new Set<string>();\n const recStack = new Set<string>();\n const cycles: string[][] = [];\n\n function dfs(node: string, path: string[]): void {\n visited.add(node);\n recStack.add(node);\n path.push(node);\n\n const nodeData = nodes.get(node);\n if (!nodeData) {return;}\n\n for (const dep of nodeData.deps) {\n if (!nodes.has(dep)) {continue;}\n if (subset && !subset.has(dep)) {continue;}\n\n if (!visited.has(dep)) {\n dfs(dep, [...path]);\n } else if (recStack.has(dep)) {\n // Found cycle\n const cycleStart = path.indexOf(dep);\n if (cycleStart !== -1) {\n const cycle = path.slice(cycleStart);\n cycles.push([...cycle, dep]);\n }\n }\n }\n\n recStack.delete(node);\n }\n\n const nodesToCheck = subset ?? new Set(nodes.keys());\n for (const node of nodesToCheck) {\n if (!visited.has(node)) {\n dfs(node, []);\n }\n }\n\n return cycles;\n}\n\n/**\n * Get build order for a specific package and its dependencies\n */\nexport function getBuildOrderForPackage(\n graph: DependencyGraph,\n packageName: string\n): TopologicalSortResult {\n const { nodes } = graph;\n\n // Find all dependencies recursively\n const allDeps = new Set<string>();\n const queue = [packageName];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n allDeps.add(current);\n\n const node = nodes.get(current);\n if (!node) {continue;}\n\n for (const dep of node.deps) {\n if (!allDeps.has(dep) && nodes.has(dep)) {\n queue.push(dep);\n }\n }\n }\n\n // Create subgraph with only relevant packages\n const subgraph: DependencyGraph = {\n nodes: new Map(),\n workspacePackages: graph.workspacePackages,\n };\n\n for (const pkg of allDeps) {\n const node = nodes.get(pkg);\n if (node) {\n subgraph.nodes.set(pkg, node);\n }\n }\n\n return topologicalSort(subgraph);\n}\n\n/**\n * Reverse dependency graph - who depends on this package\n */\nexport function getReverseDependencies(\n graph: DependencyGraph,\n packageName: string\n): Set<string> {\n const { nodes } = graph;\n const reverseDeps = new Set<string>();\n\n for (const [name, node] of nodes) {\n if (node.deps.has(packageName)) {\n reverseDeps.add(name);\n }\n }\n\n return reverseDeps;\n}\n\n/**\n * Get impact analysis - all packages affected by changes to this package\n */\nexport function getImpactAnalysis(\n graph: DependencyGraph,\n packageName: string\n): Set<string> {\n const affected = new Set<string>();\n const queue = [packageName];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n const reverseDeps = getReverseDependencies(graph, current);\n\n for (const dep of reverseDeps) {\n if (!affected.has(dep)) {\n affected.add(dep);\n queue.push(dep);\n }\n }\n }\n\n return affected;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../home/runner/work/kb-labs/kb-labs/plugins/quality/core/src/graph/dependency-graph.ts"],"names":["path"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Dependency graph utilities for monorepo analysis\n *\n * Provides topological sorting, circular dependency detection,\n * and build order calculation based on workspace dependencies.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface PackageNode {\n name: string;\n path: string;\n dir: string;\n deps: Set<string>;\n devDeps?: Set<string>;\n dependents: Set<string>; // Packages that depend on this one\n}\n\nexport interface DependencyGraph {\n nodes: Map<string, PackageNode>;\n workspacePackages: Set<string>;\n}\n\nexport interface TopologicalSortResult {\n layers: string[][]; // Build layers - each layer can build in parallel\n sorted: string[]; // Flattened topological order\n circular: string[][]; // Circular dependency chains\n}\n\n/**\n * Build dependency graph from monorepo packages\n */\nexport function buildDependencyGraph(rootDir: string): DependencyGraph {\n const nodes = new Map<string, PackageNode>();\n const workspacePackages = new Set<string>();\n\n if (!fs.existsSync(rootDir)) {\n return { nodes, workspacePackages };\n }\n\n const entries = fs.readdirSync(rootDir, { withFileTypes: true });\n\n // First pass: collect all workspace packages\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\n if (fs.existsSync(packageJsonPath)) {\n const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const packageName = pkgJson.name;\n\n if (packageName) {\n workspacePackages.add(packageName);\n }\n }\n }\n }\n\n // Second pass: build dependency graph\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\n if (fs.existsSync(packageJsonPath)) {\n const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const packageName = pkgJson.name;\n\n if (!packageName) {continue;}\n\n const deps = new Set<string>();\n const devDeps = new Set<string>();\n\n // Collect workspace dependencies\n const allDeps = {\n ...pkgJson.dependencies,\n ...pkgJson.devDependencies,\n };\n\n for (const dep of Object.keys(allDeps)) {\n if (workspacePackages.has(dep)) {\n deps.add(dep);\n }\n }\n\n // Separate dev dependencies\n if (pkgJson.devDependencies) {\n for (const dep of Object.keys(pkgJson.devDependencies)) {\n if (workspacePackages.has(dep)) {\n devDeps.add(dep);\n }\n }\n }\n\n nodes.set(packageName, {\n name: packageName,\n path: packageJsonPath,\n dir: path.dirname(packageJsonPath),\n deps,\n devDeps,\n dependents: new Set(),\n });\n }\n }\n }\n\n // Second pass: calculate reverse dependencies (dependents)\n for (const [packageName, node] of nodes) {\n for (const dep of node.deps) {\n const depNode = nodes.get(dep);\n if (depNode) {\n depNode.dependents.add(packageName);\n }\n }\n }\n\n return { nodes, workspacePackages };\n}\n\n/**\n * Topological sort using Kahn's algorithm\n * Returns build layers where each layer can be built in parallel\n */\nexport function topologicalSort(graph: DependencyGraph): TopologicalSortResult {\n const { nodes } = graph;\n const layers: string[][] = [];\n const sorted: string[] = [];\n const circular: string[][] = [];\n\n // Calculate in-degree for each node\n const inDegree = new Map<string, number>();\n for (const [name] of nodes) {\n inDegree.set(name, 0);\n }\n\n for (const [, node] of nodes) {\n for (const dep of node.deps) {\n if (nodes.has(dep)) {\n inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);\n }\n }\n }\n\n // Kahn's algorithm with layers\n const queue: string[] = [];\n for (const [name, degree] of inDegree) {\n if (degree === 0) {\n queue.push(name);\n }\n }\n\n while (queue.length > 0) {\n const layer: string[] = [...queue];\n layers.push(layer);\n sorted.push(...layer);\n queue.length = 0;\n\n for (const name of layer) {\n const node = nodes.get(name);\n if (!node) {continue;}\n\n for (const dep of node.deps) {\n if (nodes.has(dep)) {\n const newDegree = (inDegree.get(dep) ?? 0) - 1;\n inDegree.set(dep, newDegree);\n if (newDegree === 0) {\n queue.push(dep);\n }\n }\n }\n }\n }\n\n // Check for circular dependencies\n if (sorted.length < nodes.size) {\n const remaining = new Set<string>();\n for (const [name] of nodes) {\n if (!sorted.includes(name)) {\n remaining.add(name);\n }\n }\n\n // Find cycles using DFS\n const cycles = findCircularDependencies(graph, remaining);\n circular.push(...cycles);\n }\n\n return { layers, sorted, circular };\n}\n\n/**\n * Find circular dependencies using DFS\n */\nexport function findCircularDependencies(\n graph: DependencyGraph,\n subset?: Set<string>\n): string[][] {\n const { nodes } = graph;\n const visited = new Set<string>();\n const recStack = new Set<string>();\n const cycles: string[][] = [];\n\n function dfs(node: string, path: string[]): void {\n visited.add(node);\n recStack.add(node);\n path.push(node);\n\n const nodeData = nodes.get(node);\n if (!nodeData) {return;}\n\n for (const dep of nodeData.deps) {\n if (!nodes.has(dep)) {continue;}\n if (subset && !subset.has(dep)) {continue;}\n\n if (!visited.has(dep)) {\n dfs(dep, [...path]);\n } else if (recStack.has(dep)) {\n // Found cycle\n const cycleStart = path.indexOf(dep);\n if (cycleStart !== -1) {\n const cycle = path.slice(cycleStart);\n cycles.push([...cycle, dep]);\n }\n }\n }\n\n recStack.delete(node);\n }\n\n const nodesToCheck = subset ?? new Set(nodes.keys());\n for (const node of nodesToCheck) {\n if (!visited.has(node)) {\n dfs(node, []);\n }\n }\n\n return cycles;\n}\n\n/**\n * Get build order for a specific package and its dependencies\n */\nexport function getBuildOrderForPackage(\n graph: DependencyGraph,\n packageName: string\n): TopologicalSortResult {\n const { nodes } = graph;\n\n // Find all dependencies recursively\n const allDeps = new Set<string>();\n const queue = [packageName];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n allDeps.add(current);\n\n const node = nodes.get(current);\n if (!node) {continue;}\n\n for (const dep of node.deps) {\n if (!allDeps.has(dep) && nodes.has(dep)) {\n queue.push(dep);\n }\n }\n }\n\n // Create subgraph with only relevant packages\n const subgraph: DependencyGraph = {\n nodes: new Map(),\n workspacePackages: graph.workspacePackages,\n };\n\n for (const pkg of allDeps) {\n const node = nodes.get(pkg);\n if (node) {\n subgraph.nodes.set(pkg, node);\n }\n }\n\n return topologicalSort(subgraph);\n}\n\n/**\n * Reverse dependency graph - who depends on this package\n */\nexport function getReverseDependencies(\n graph: DependencyGraph,\n packageName: string\n): Set<string> {\n const { nodes } = graph;\n const reverseDeps = new Set<string>();\n\n for (const [name, node] of nodes) {\n if (node.deps.has(packageName)) {\n reverseDeps.add(name);\n }\n }\n\n return reverseDeps;\n}\n\n/**\n * Get impact analysis - all packages affected by changes to this package\n */\nexport function getImpactAnalysis(\n graph: DependencyGraph,\n packageName: string\n): Set<string> {\n const affected = new Set<string>();\n const queue = [packageName];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n const reverseDeps = getReverseDependencies(graph, current);\n\n for (const dep of reverseDeps) {\n if (!affected.has(dep)) {\n affected.add(dep);\n queue.push(dep);\n }\n }\n }\n\n return affected;\n}\n"]}
|