react-prune 2.0.1 → 2.0.2
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/bin/react-prune +8 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/bin/react-prune
CHANGED
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
# bin/react-prune
|
|
4
4
|
|
|
5
5
|
# Get the directory where the script is located
|
|
6
|
-
|
|
6
|
+
# Get the directory where the script is located, resolving symlinks
|
|
7
|
+
SOURCE="${BASH_SOURCE[0]}"
|
|
8
|
+
while [ -h "$SOURCE" ]; do
|
|
9
|
+
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
|
|
10
|
+
SOURCE="$(readlink "$SOURCE")"
|
|
11
|
+
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
|
|
12
|
+
done
|
|
13
|
+
SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
|
|
7
14
|
PROJECT_ROOT="$(pwd)"
|
|
8
15
|
|
|
9
16
|
CORE_DIR="$SCRIPT_DIR/../scripts/core"
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';var x=require('path'),commander=require('commander'),f=require('picocolors'),F=require('cli-table3'),E=require('boxen'),tsMorph=require('ts-morph'),V=require('fast-glob'),k=require('fs');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var x__default=/*#__PURE__*/_interopDefault(x);var f__default=/*#__PURE__*/_interopDefault(f);var F__default=/*#__PURE__*/_interopDefault(F);var E__default=/*#__PURE__*/_interopDefault(E);var V__default=/*#__PURE__*/_interopDefault(V);var k__default=/*#__PURE__*/_interopDefault(k);var T=Object.defineProperty;var P=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,s)=>(typeof require<"u"?require:t)[s]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var L=(e,t)=>()=>(e&&(t=e(e=0)),t);var _=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),q=(e,t)=>{for(var s in t)T(e,s,{get:t[s],enumerable:true});};var I=_((fe,X)=>{X.exports={name:"react-prune",version:"2.0.
|
|
2
|
+
'use strict';var x=require('path'),commander=require('commander'),f=require('picocolors'),F=require('cli-table3'),E=require('boxen'),tsMorph=require('ts-morph'),V=require('fast-glob'),k=require('fs');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var x__default=/*#__PURE__*/_interopDefault(x);var f__default=/*#__PURE__*/_interopDefault(f);var F__default=/*#__PURE__*/_interopDefault(F);var E__default=/*#__PURE__*/_interopDefault(E);var V__default=/*#__PURE__*/_interopDefault(V);var k__default=/*#__PURE__*/_interopDefault(k);var T=Object.defineProperty;var P=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,s)=>(typeof require<"u"?require:t)[s]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var L=(e,t)=>()=>(e&&(t=e(e=0)),t);var _=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),q=(e,t)=>{for(var s in t)T(e,s,{get:t[s],enumerable:true});};var I=_((fe,X)=>{X.exports={name:"react-prune",version:"2.0.2",main:"dist/index.js",bin:{"react-prune":"./bin/react-prune"},scripts:{build:"tsup src/cli.ts --format cjs --dts",dev:"tsup src/cli.ts --watch",lint:"eslint src/**",format:"prettier --write .",prepublishOnly:"npm run build",release:"changeset publish",test:"vitest"},publishConfig:{access:"public"},keywords:["react","react-native","nextjs","analysis","dead-code","imports","dependency-analysis","bundle-size","prune","typescript","developer-tools","cli"],author:"Daniel Arikawe",license:"MIT",files:["bin","scripts","dist"],repository:{type:"git",url:"git+https://github.com/danieljohnson18/react-prune.git"},engines:{node:">=18"},bugs:{url:"https://github.com/danieljohnson18/react-prune/issues"},homepage:"https://github.com/danieljohnson18/react-prune#readme",description:"A powerful CLI tool to monitor package usage, analyze component imports, and detect dead code across React, Next.js, and React Native applications.",dependencies:{boxen:"^8.0.1","cli-table3":"^0.6.5",commander:"^14.0.2",depcheck:"^1.4.7","fast-glob":"^3.3.3",picocolors:"^1.1.1","ts-morph":"^27.0.2"},devDependencies:{"@changesets/cli":"^2.29.8","@types/depcheck":"^0.9.0","@types/glob":"^8.1.0","@types/node":"^25.0.10",eslint:"^9.39.2",prettier:"^3.8.1",tsup:"^8.5.1",typescript:"^5.9.3",vitest:"^4.0.18"}};});var N={};q(N,{getPackageSize:()=>Z});function Z(e,t){try{let s=P(x__default.default.join(e,"node_modules",t,"package.json"));if(typeof s.size=="number")return `${(s.size/1024).toFixed(2)} KB`}catch{}}var B=L(()=>{});function C(e){let t=0;try{let s=k__default.default.readdirSync(e);for(let i of s){let l=x__default.default.join(e,i),o=k__default.default.statSync(l);o.isDirectory()?t+=C(l):t+=o.size;}}catch{}return t}function G(e,t=2){if(e===0)return "0 Bytes";let s=1024,i=t<0?0:t,l=["Bytes","KB","MB","GB","TB"],o=Math.floor(Math.log(e)/Math.log(s));return parseFloat((e/Math.pow(s,o)).toFixed(i))+" "+l[o]}function H(e,t){let s=x__default.default.join(e,"node_modules",t);return k__default.default.existsSync(s)?G(C(s)):"N/A"}async function v(e){let{rootPath:t,includeSizes:s=true,analyzeExports:i=true,silent:l=false}=e;l||console.log(f__default.default.green(`Analyzing project at ${t}`));let o=await V__default.default("**/*.{js,jsx,ts,tsx}",{cwd:t,ignore:["**/node_modules/**","**/dist/**","**/build/**","**/.next/**","**/coverage/**","**/*.config.{js,ts,cjs,mjs}","**/*.d.ts"],absolute:true});l||console.log(f__default.default.blue(`Found ${o.length} files to analyze.`));let r=new tsMorph.Project({skipAddingFilesFromTsConfig:true}),m=x__default.default.join(t,"tsconfig.json");k__default.default.existsSync(m)&&r.addSourceFilesFromTsConfig(m),o.forEach(n=>{try{r.addSourceFileAtPath(n);}catch{console.warn(f__default.default.yellow(`Skipping ${n}`));}});let u={},h={},d={},D={};for(let n of r.getSourceFiles()){let a=x__default.default.relative(t,n.getFilePath()).replace(/\\/g,"/");D[a]=n;let y=n.getExportedDeclarations(),g=new Set;y.forEach((S,c)=>{c!=="default"&&g.add(c);});let b=y.has("default");h[a]={named:g,default:b},d[a]=new Set,n.getImportDeclarations().forEach(S=>{let c=S.getModuleSpecifierValue();if(!c.startsWith(".")&&!c.startsWith("/")){let p=c.startsWith("@")?c.split("/").slice(0,2).join("/"):c.split("/")[0];u[p]=(u[p]||0)+1;}}),n.getDescendantsOfKind(tsMorph.SyntaxKind.CallExpression).forEach(S=>{if(S.getExpression().getText()==="require"){let c=S.getArguments();if(c.length&&c[0].getKind()===tsMorph.SyntaxKind.StringLiteral){let p=c[0].getText().replace(/['"`]/g,"");if(!p.startsWith(".")&&!p.startsWith("/")){let z=p.startsWith("@")?p.split("/").slice(0,2).join("/"):p.split("/")[0];u[z]=(u[z]||0)+1;}}}});}if(i)for(let n of r.getSourceFiles()){let a=n.getImportDeclarations();x__default.default.relative(t,n.getFilePath()).replace(/\\/g,"/");a.forEach(g=>{let b=g.getModuleSpecifierValue();if(b.startsWith(".")||b.startsWith("/")){let A=x__default.default.dirname(n.getFilePath()),W=x__default.default.resolve(A,b),S=["",".ts",".tsx",".js",".jsx","/index.ts","/index.tsx","/index.js","/index.jsx"],c;for(let p of S){let z=x__default.default.relative(t,W+p).replace(/\\/g,"/");if(h[z]){c=z;break}}c&&(g.getNamedImports().forEach(p=>d[c].add(p.getName())),g.getDefaultImport()&&d[c].add("default"));}});}let K=Object.entries(h).filter(([n,a])=>{if(n.includes("pages/")||n.includes("app/")||n.endsWith("index.tsx")||n.endsWith("App.tsx"))return false;let y=d[n];return a.named.size===0&&!a.default?false:y.size===0}).map(([n])=>n),R={};i&&Object.entries(h).forEach(([n,a])=>{let y=d[n],g=[];a.default&&!y.has("default")&&g.push("default"),a.named.forEach(b=>{y.has(b)||g.push(b);}),g.length&&(R[n]=g);});let $={};Object.entries(u).forEach(([n,a])=>{$[n]={count:a,size:s?H(t,n):"\u2014"};});let O=[];try{O=(await P("depcheck")(t,{ignoreMatches:["react-prune",...e.ignoreMatches||[]],skipMissing:!0})).dependencies;}catch{l||console.warn(f__default.default.yellow("Failed to run depcheck."));}return {packages:$,unusedFiles:K,unusedExports:R,usedExports:d,unusedDependencies:O,sourceFiles:D}}function M(e){try{let s=k__default.default.statSync(e).size;return s<1024?`${s} B`:`${(s/1024).toFixed(2)} KB`}catch{return "N/A"}}var j=new commander.Command;j.name("react-prune").description("Analyze React/Next/Vite/React Native projects").version(I().version).option("--no-size","Skip package size calculation").option("--no-exports","Skip export usage analysis").option("--limit <n>","Limit output rows per table","50");j.command("analyze").description("Run full project analysis").option("--no-size","Skip package size calculation").option("--no-exports","Skip export usage analysis").option("--limit <n>","Limit output rows per table","50").option("--json","Output results as JSON").action(async e=>{let t=process.cwd(),s=Number(e.limit),i=await v({rootPath:t,includeSizes:e.size,analyzeExports:e.exports,silent:e.json});if(e.json){let{sourceFiles:o,usedExports:r,...m}=i,u={};if(r)for(let[h,d]of Object.entries(r))u[h]=Array.from(d);console.log(JSON.stringify({...m,usedExports:u},null,2));return}let l=new F__default.default({head:[f__default.default.cyan("Package"),"Count","Size"],colWidths:[40,10,15]});if(Object.entries(i.packages).sort((o,r)=>r[1].count-o[1].count).slice(0,s).forEach(([o,r])=>l.push([o,r.count,r.size])),console.log(E__default.default(f__default.default.bold("\u{1F4E6} Package Usage"),{padding:1,borderColor:"green",borderStyle:"round"})),console.log(l.toString()),i.unusedFiles.length){let o=new F__default.default({head:[f__default.default.yellow("Unused Files")],colWidths:[80]});i.unusedFiles.slice(0,s).forEach(r=>o.push([r])),console.log(E__default.default(f__default.default.bold(`\u26A0\uFE0F Unused Files (${i.unusedFiles.length})`),{padding:1,borderColor:"yellow",borderStyle:"round"})),console.log(o.toString());}if(e.exports){let o=Object.entries(i.unusedExports);if(o.length){let r=new F__default.default({head:["File","Unused Exports"],colWidths:[50,40],wordWrap:true});o.slice(0,s).forEach(([m,u])=>r.push([m,u.join(", ")])),console.log(E__default.default(f__default.default.bold("\u26A0\uFE0F Unused Exports"),{padding:1,borderColor:"yellow",borderStyle:"round"})),console.log(r.toString());}}if(i.unusedDependencies&&i.unusedDependencies.length){let o=new F__default.default({head:[f__default.default.yellow("Unused Dependencies")],colWidths:[80]});i.unusedDependencies.slice(0,s).forEach(r=>o.push([r])),console.log(E__default.default(f__default.default.bold(`\u26A0\uFE0F Unused Dependencies (${i.unusedDependencies.length})`),{padding:1,borderColor:"yellow",borderStyle:"round"})),console.log(o.toString());}});j.command("size <packageName>").description("Check the size of a specific npm package in node_modules").action(async e=>{let t=process.cwd(),{getPackageSize:s}=await Promise.resolve().then(()=>(B(),N)),i=s(t,e);console.log(i==="N/A"?f__default.default.yellow(`Package '${e}' not found in node_modules.`):f__default.default.green(`\u{1F4E6} ${e} size: ${i}`));});j.command("find <exportName>").description("Find usage count and references (with line numbers) for a component/function/export").action(async e=>{let t=process.cwd(),s=await v({rootPath:t,analyzeExports:true,includeSizes:false}),i=[],l=s.usedExports||{};for(let[o,r]of Object.entries(l)){let m=s.sourceFiles?.[o];if(!m||!r.has(e))continue;m.getDescendantsOfKind(tsMorph.SyntaxKind.Identifier).forEach(h=>{if(h.getText()===e){let d=h.getParentOrThrow().getKindName();(d.includes("Import")||d.includes("PropertyAccess")||d.includes("Identifier"))&&i.push({file:o,line:h.getStartLineNumber()});}});}i.length?(console.log(f__default.default.green(`'${e}' is used ${i.length} time(s):`)),i.forEach(o=>{let r=M(x__default.default.join(t,o.file));console.log(` - ${o.file}:${o.line} (${r})`);})):console.log(f__default.default.yellow(`'${e}' is not used anywhere.`));});j.parse(process.argv);
|
|
3
3
|
//# sourceMappingURL=cli.js.map
|
|
4
4
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/analyzer/package-size.ts","../src/analyzer/index.ts","../src/analyzer/file-size.ts","../src/cli.ts"],"names":["require_package","__commonJSMin","exports","module","package_size_exports","__export","getPackageSize","rootPath","pkg","pkgJson","__require","path","init_package_size","__esmMin","getFolderSize","dirPath","size","files","fs","file","filePath","stats","formatBytes","bytes","decimals","k","dm","sizes","i","packageName","pkgPath","analyzeProject","options","includeSizes","analyzeExports","silent","pc","glob","project","Project","tsConfigPath","f","packageUsage","fileExports","usedExports","sourceFiles","sourceFile","relativePath","exportsMap","namedExports","decls","name","hasDefault","imp","mod","SyntaxKind","call","args","imports","sourceDir","resolvedPath","extensions","foundFile","ext","tryPath","ni","unusedFiles","used","unusedExports","unused","packages","count","unusedDependencies","getFileSize","program","Command","opts","limit","report","rest","sanitizedUsedExports","key","value","packageTable","Table","a","b","data","boxen","table","entries","d","exportName","usageDetails","usedSet","id","parentKind"],"mappings":"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","file":"cli.js","sourcesContent":["{\n \"name\": \"react-prune\",\n \"version\": \"2.0.1\",\n \"main\": \"dist/index.js\",\n \"bin\": {\n \"react-prune\": \"./bin/react-prune\"\n },\n \"scripts\": {\n \"build\": \"tsup src/cli.ts --format cjs --dts\",\n \"dev\": \"tsup src/cli.ts --watch\",\n \"lint\": \"eslint src/**\",\n \"format\": \"prettier --write .\",\n \"prepublishOnly\": \"npm run build\",\n \"release\": \"changeset publish\",\n \"test\": \"vitest\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"react\",\n \"react-native\",\n \"nextjs\",\n \"analysis\",\n \"dead-code\",\n \"imports\",\n \"dependency-analysis\",\n \"bundle-size\",\n \"prune\",\n \"typescript\",\n \"developer-tools\",\n \"cli\"\n ],\n \"author\": \"Daniel Arikawe\",\n \"license\": \"MIT\",\n \"files\": [\n \"bin\",\n \"scripts\",\n \"dist\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/danieljohnson18/react-prune.git\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/danieljohnson18/react-prune/issues\"\n },\n \"homepage\": \"https://github.com/danieljohnson18/react-prune#readme\",\n \"description\": \"A powerful CLI tool to monitor package usage, analyze component imports, and detect dead code across React, Next.js, and React Native applications.\",\n \"dependencies\": {\n \"boxen\": \"^8.0.1\",\n \"cli-table3\": \"^0.6.5\",\n \"commander\": \"^14.0.2\",\n \"depcheck\": \"^1.4.7\",\n \"fast-glob\": \"^3.3.3\",\n \"picocolors\": \"^1.1.1\",\n \"ts-morph\": \"^27.0.2\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.29.8\",\n \"@types/depcheck\": \"^0.9.0\",\n \"@types/glob\": \"^8.1.0\",\n \"@types/node\": \"^25.0.10\",\n \"eslint\": \"^9.39.2\",\n \"prettier\": \"^3.8.1\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.0.18\"\n }\n}\n","import path from \"path\";\n\nexport function getPackageSize(\n rootPath: string,\n pkg: string\n): string | undefined {\n try {\n const pkgJson = require(\n path.join(rootPath, \"node_modules\", pkg, \"package.json\")\n );\n if (typeof pkgJson.size === \"number\") {\n return `${(pkgJson.size / 1024).toFixed(2)} KB`;\n }\n } catch {}\n return undefined;\n}\n","import { Project, SyntaxKind, SourceFile } from \"ts-morph\";\nimport glob from \"fast-glob\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport pc from \"picocolors\";\nimport { AnalyzerOptions, UsageReport } from \"./types\";\n\nexport * from \"./types\";\n\nfunction getFolderSize(dirPath: string): number {\n let size = 0;\n try {\n const files = fs.readdirSync(dirPath);\n for (const file of files) {\n const filePath = path.join(dirPath, file);\n const stats = fs.statSync(filePath);\n if (stats.isDirectory()) size += getFolderSize(filePath);\n else size += stats.size;\n }\n } catch {}\n return size;\n}\n\nfunction formatBytes(bytes: number, decimals = 2) {\n if (bytes === 0) return \"0 Bytes\";\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + \" \" + sizes[i];\n}\n\nfunction getPackageSize(rootPath: string, packageName: string): string {\n const pkgPath = path.join(rootPath, \"node_modules\", packageName);\n if (fs.existsSync(pkgPath)) return formatBytes(getFolderSize(pkgPath));\n return \"N/A\";\n}\n\nexport async function analyzeProject(\n options: AnalyzerOptions\n): Promise<UsageReport> {\n const {\n rootPath,\n includeSizes = true,\n analyzeExports = true,\n silent = false\n } = options;\n\n if (!silent) {\n console.log(pc.green(`Analyzing project at ${rootPath}`));\n }\n\n // 1️⃣ Collect all JS/TS files\n const files = await glob(\"**/*.{js,jsx,ts,tsx}\", {\n cwd: rootPath,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/coverage/**\",\n \"**/*.config.{js,ts,cjs,mjs}\",\n \"**/*.d.ts\"\n ],\n absolute: true\n });\n\n if (!silent) {\n console.log(pc.blue(`Found ${files.length} files to analyze.`));\n }\n\n const project = new Project({ skipAddingFilesFromTsConfig: true });\n const tsConfigPath = path.join(rootPath, \"tsconfig.json\");\n if (fs.existsSync(tsConfigPath)) {\n project.addSourceFilesFromTsConfig(tsConfigPath);\n }\n files.forEach((f) => {\n try {\n project.addSourceFileAtPath(f);\n } catch {\n console.warn(pc.yellow(`Skipping ${f}`));\n }\n });\n\n // 2️⃣ Track package usage and file exports\n const packageUsage: Record<string, number> = {};\n const fileExports: Record<string, { named: Set<string>; default: boolean }> =\n {};\n const usedExports: Record<string, Set<string>> = {};\n const sourceFiles: Record<string, SourceFile> = {};\n\n for (const sourceFile of project.getSourceFiles()) {\n const relativePath = path\n .relative(rootPath, sourceFile.getFilePath())\n .replace(/\\\\/g, \"/\");\n sourceFiles[relativePath] = sourceFile;\n\n const exportsMap = sourceFile.getExportedDeclarations();\n const namedExports = new Set<string>();\n exportsMap.forEach((decls, name) => {\n if (name !== \"default\") namedExports.add(name);\n });\n const hasDefault = exportsMap.has(\"default\");\n\n fileExports[relativePath] = { named: namedExports, default: hasDefault };\n usedExports[relativePath] = new Set();\n\n // Track package imports\n const imports = sourceFile.getImportDeclarations();\n imports.forEach((imp) => {\n const mod = imp.getModuleSpecifierValue();\n if (!mod.startsWith(\".\") && !mod.startsWith(\"/\")) {\n const pkg = mod.startsWith(\"@\")\n ? mod.split(\"/\").slice(0, 2).join(\"/\")\n : mod.split(\"/\")[0];\n packageUsage[pkg] = (packageUsage[pkg] || 0) + 1;\n }\n });\n\n // Track require()\n const calls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);\n calls.forEach((call) => {\n if (call.getExpression().getText() === \"require\") {\n const args = call.getArguments();\n if (args.length && args[0].getKind() === SyntaxKind.StringLiteral) {\n const mod = args[0].getText().replace(/['\"`]/g, \"\");\n if (!mod.startsWith(\".\") && !mod.startsWith(\"/\")) {\n const pkg = mod.startsWith(\"@\")\n ? mod.split(\"/\").slice(0, 2).join(\"/\")\n : mod.split(\"/\")[0];\n packageUsage[pkg] = (packageUsage[pkg] || 0) + 1;\n }\n }\n }\n });\n }\n\n // 3️⃣ Track used exports across files\n if (analyzeExports) {\n for (const sourceFile of project.getSourceFiles()) {\n const imports = sourceFile.getImportDeclarations();\n const relativePath = path\n .relative(rootPath, sourceFile.getFilePath())\n .replace(/\\\\/g, \"/\");\n\n imports.forEach((imp) => {\n const mod = imp.getModuleSpecifierValue();\n if (mod.startsWith(\".\") || mod.startsWith(\"/\")) {\n const sourceDir = path.dirname(sourceFile.getFilePath());\n let resolvedPath = path.resolve(sourceDir, mod);\n const extensions = [\n \"\",\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \"/index.ts\",\n \"/index.tsx\",\n \"/index.js\",\n \"/index.jsx\"\n ];\n let foundFile: string | undefined;\n\n for (const ext of extensions) {\n const tryPath = path\n .relative(rootPath, resolvedPath + ext)\n .replace(/\\\\/g, \"/\");\n if (fileExports[tryPath]) {\n foundFile = tryPath;\n break;\n }\n }\n\n if (foundFile) {\n imp\n .getNamedImports()\n .forEach((ni) => usedExports[foundFile].add(ni.getName()));\n if (imp.getDefaultImport()) usedExports[foundFile].add(\"default\");\n }\n }\n });\n }\n }\n\n // 4️⃣ Determine unused files and exports\n const unusedFiles = Object.entries(fileExports)\n .filter(([file, exports]) => {\n if (\n file.includes(\"pages/\") ||\n file.includes(\"app/\") ||\n file.endsWith(\"index.tsx\") ||\n file.endsWith(\"App.tsx\")\n )\n return false;\n const used = usedExports[file];\n if (exports.named.size === 0 && !exports.default) return false;\n return used.size === 0;\n })\n .map(([file]) => file);\n\n const unusedExports: Record<string, string[]> = {};\n if (analyzeExports) {\n Object.entries(fileExports).forEach(([file, exports]) => {\n const used = usedExports[file];\n const unused: string[] = [];\n if (exports.default && !used.has(\"default\")) unused.push(\"default\");\n exports.named.forEach((name) => {\n if (!used.has(name)) unused.push(name);\n });\n if (unused.length) unusedExports[file] = unused;\n });\n }\n\n // 5️⃣ Build package report\n const packages: Record<string, { count: number; size: string }> = {};\n Object.entries(packageUsage).forEach(([pkg, count]) => {\n packages[pkg] = {\n count,\n size: includeSizes ? getPackageSize(rootPath, pkg) : \"—\"\n };\n });\n\n // 6️⃣ Run depcheck\n let unusedDependencies: string[] = [];\n try {\n const depcheck = require(\"depcheck\");\n // We can't easily wait for this if not async, but analyzeProject is async.\n const depcheckResult = await depcheck(rootPath, {\n ignoreMatches: [\"react-prune\", ...((options as any).ignoreMatches || [])],\n skipMissing: true\n });\n unusedDependencies = depcheckResult.dependencies;\n } catch (e) {\n if (!silent) console.warn(pc.yellow(\"Failed to run depcheck.\"));\n }\n\n return {\n packages,\n unusedFiles,\n unusedExports,\n usedExports,\n unusedDependencies,\n sourceFiles\n };\n}\n\nexport { getPackageSize };\n","import fs from \"fs\";\n\nexport function getFileSize(filePath: string): string {\n try {\n const stats = fs.statSync(filePath);\n const bytes = stats.size;\n if (bytes < 1024) return `${bytes} B`;\n return `${(bytes / 1024).toFixed(2)} KB`;\n } catch {\n return \"N/A\";\n }\n}\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport Table from \"cli-table3\";\nimport boxen from \"boxen\";\nimport path from \"path\";\nimport { analyzeProject, UsageReport } from \"./analyzer\";\nimport { getFileSize } from \"./analyzer/file-size\";\nimport { SyntaxKind, Identifier } from \"ts-morph\";\n\nconst program = new Command();\n\nprogram\n .name(\"react-prune\")\n .description(\"Analyze React/Next/Vite/React Native projects\")\n .version(require(\"../package.json\").version)\n .option(\"--no-size\", \"Skip package size calculation\")\n .option(\"--no-exports\", \"Skip export usage analysis\")\n .option(\"--limit <n>\", \"Limit output rows per table\", \"50\");\n\nprogram\n .command(\"analyze\")\n .description(\"Run full project analysis\")\n .option(\"--no-size\", \"Skip package size calculation\")\n .option(\"--no-exports\", \"Skip export usage analysis\")\n .option(\"--limit <n>\", \"Limit output rows per table\", \"50\")\n .option(\"--json\", \"Output results as JSON\")\n .action(async (opts) => {\n const rootPath = process.cwd();\n const limit = Number(opts.limit);\n\n const report: UsageReport = await analyzeProject({\n rootPath,\n includeSizes: opts.size,\n analyzeExports: opts.exports,\n silent: opts.json\n });\n\n if (opts.json) {\n // 1. Remove circular references (sourceFiles)\n // 2. Convert Sets to Arrays for valid JSON\n const { sourceFiles, usedExports, ...rest } = report;\n\n const sanitizedUsedExports: Record<string, string[]> = {};\n if (usedExports) {\n for (const [key, value] of Object.entries(usedExports)) {\n sanitizedUsedExports[key] = Array.from(value);\n }\n }\n\n console.log(\n JSON.stringify(\n {\n ...rest,\n usedExports: sanitizedUsedExports\n },\n null,\n 2\n )\n );\n return;\n }\n\n // Packages\n const packageTable = new Table({\n head: [pc.cyan(\"Package\"), \"Count\", \"Size\"],\n colWidths: [40, 10, 15]\n });\n Object.entries(report.packages)\n .sort((a, b) => b[1].count - a[1].count)\n .slice(0, limit)\n .forEach(([pkg, data]) =>\n packageTable.push([pkg, data.count, data.size])\n );\n console.log(\n boxen(pc.bold(\"📦 Package Usage\"), {\n padding: 1,\n borderColor: \"green\",\n borderStyle: \"round\"\n })\n );\n console.log(packageTable.toString());\n\n // Unused Files\n if (report.unusedFiles.length) {\n const table = new Table({\n head: [pc.yellow(\"Unused Files\")],\n colWidths: [80]\n });\n report.unusedFiles.slice(0, limit).forEach((f) => table.push([f]));\n console.log(\n boxen(pc.bold(`⚠️ Unused Files (${report.unusedFiles.length})`), {\n padding: 1,\n borderColor: \"yellow\",\n borderStyle: \"round\"\n })\n );\n console.log(table.toString());\n }\n\n // Unused Exports\n if (opts.exports) {\n const entries = Object.entries(report.unusedExports);\n if (entries.length) {\n const table = new Table({\n head: [\"File\", \"Unused Exports\"],\n colWidths: [50, 40],\n wordWrap: true\n });\n entries\n .slice(0, limit)\n .forEach(([file, exports]) => table.push([file, exports.join(\", \")]));\n console.log(\n boxen(pc.bold(`⚠️ Unused Exports`), {\n padding: 1,\n borderColor: \"yellow\",\n borderStyle: \"round\"\n })\n );\n console.log(table.toString());\n }\n }\n\n // Unused Dependencies\n if (report.unusedDependencies && report.unusedDependencies.length) {\n const table = new Table({\n head: [pc.yellow(\"Unused Dependencies\")],\n colWidths: [80]\n });\n report.unusedDependencies.slice(0, limit).forEach((d) => table.push([d]));\n console.log(\n boxen(\n pc.bold(\n `⚠️ Unused Dependencies (${report.unusedDependencies.length})`\n ),\n {\n padding: 1,\n borderColor: \"yellow\",\n borderStyle: \"round\"\n }\n )\n );\n console.log(table.toString());\n }\n });\n\nprogram\n .command(\"size <packageName>\")\n .description(\"Check the size of a specific npm package in node_modules\")\n .action(async (packageName) => {\n const rootPath = process.cwd();\n\n // Reuse helper from analyzer\n const { getPackageSize } = await import(\"./analyzer/package-size\");\n\n const size = getPackageSize(rootPath, packageName);\n\n if (size === \"N/A\") {\n console.log(\n pc.yellow(`Package '${packageName}' not found in node_modules.`)\n );\n } else {\n console.log(pc.green(`📦 ${packageName} size: ${size}`));\n }\n });\n// --- New find command with line numbers\nprogram\n .command(\"find <exportName>\")\n .description(\n \"Find usage count and references (with line numbers) for a component/function/export\"\n )\n .action(async (exportName) => {\n const rootPath = process.cwd();\n const report: UsageReport = await analyzeProject({\n rootPath,\n analyzeExports: true,\n includeSizes: false\n });\n\n const usageDetails: { file: string; line: number }[] = [];\n\n const usedExports = report.usedExports || {};\n\n for (const [file, usedSet] of Object.entries(usedExports)) {\n const sourceFile = report.sourceFiles?.[file];\n if (!sourceFile) continue;\n\n // Only process if this file actually uses the export\n if (!usedSet.has(exportName)) continue;\n\n // Traverse identifiers in the file\n const identifiers = sourceFile.getDescendantsOfKind(\n SyntaxKind.Identifier\n );\n\n identifiers.forEach((id: Identifier) => {\n // Check if identifier matches the export name\n if (id.getText() === exportName) {\n // Make sure this usage is actually an import/reference, not a declaration\n const parentKind = id.getParentOrThrow().getKindName();\n\n if (\n parentKind.includes(\"Import\") || // ImportSpecifier, ImportClause, etc\n parentKind.includes(\"PropertyAccess\") || // obj.exportName\n parentKind.includes(\"Identifier\") // usage in code\n ) {\n usageDetails.push({ file, line: id.getStartLineNumber() });\n }\n }\n });\n }\n\n if (usageDetails.length) {\n console.log(\n pc.green(`'${exportName}' is used ${usageDetails.length} time(s):`)\n );\n usageDetails.forEach((d) => {\n const size = getFileSize(path.join(rootPath, d.file));\n console.log(` - ${d.file}:${d.line} (${size})`);\n });\n } else {\n console.log(pc.yellow(`'${exportName}' is not used anywhere.`));\n }\n });\n\nprogram.parse(process.argv);\n"]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/analyzer/package-size.ts","../src/analyzer/index.ts","../src/analyzer/file-size.ts","../src/cli.ts"],"names":["require_package","__commonJSMin","exports","module","package_size_exports","__export","getPackageSize","rootPath","pkg","pkgJson","__require","path","init_package_size","__esmMin","getFolderSize","dirPath","size","files","fs","file","filePath","stats","formatBytes","bytes","decimals","k","dm","sizes","i","packageName","pkgPath","analyzeProject","options","includeSizes","analyzeExports","silent","pc","glob","project","Project","tsConfigPath","f","packageUsage","fileExports","usedExports","sourceFiles","sourceFile","relativePath","exportsMap","namedExports","decls","name","hasDefault","imp","mod","SyntaxKind","call","args","imports","sourceDir","resolvedPath","extensions","foundFile","ext","tryPath","ni","unusedFiles","used","unusedExports","unused","packages","count","unusedDependencies","getFileSize","program","Command","opts","limit","report","rest","sanitizedUsedExports","key","value","packageTable","Table","a","b","data","boxen","table","entries","d","exportName","usageDetails","usedSet","id","parentKind"],"mappings":"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","file":"cli.js","sourcesContent":["{\n \"name\": \"react-prune\",\n \"version\": \"2.0.2\",\n \"main\": \"dist/index.js\",\n \"bin\": {\n \"react-prune\": \"./bin/react-prune\"\n },\n \"scripts\": {\n \"build\": \"tsup src/cli.ts --format cjs --dts\",\n \"dev\": \"tsup src/cli.ts --watch\",\n \"lint\": \"eslint src/**\",\n \"format\": \"prettier --write .\",\n \"prepublishOnly\": \"npm run build\",\n \"release\": \"changeset publish\",\n \"test\": \"vitest\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"react\",\n \"react-native\",\n \"nextjs\",\n \"analysis\",\n \"dead-code\",\n \"imports\",\n \"dependency-analysis\",\n \"bundle-size\",\n \"prune\",\n \"typescript\",\n \"developer-tools\",\n \"cli\"\n ],\n \"author\": \"Daniel Arikawe\",\n \"license\": \"MIT\",\n \"files\": [\n \"bin\",\n \"scripts\",\n \"dist\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/danieljohnson18/react-prune.git\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/danieljohnson18/react-prune/issues\"\n },\n \"homepage\": \"https://github.com/danieljohnson18/react-prune#readme\",\n \"description\": \"A powerful CLI tool to monitor package usage, analyze component imports, and detect dead code across React, Next.js, and React Native applications.\",\n \"dependencies\": {\n \"boxen\": \"^8.0.1\",\n \"cli-table3\": \"^0.6.5\",\n \"commander\": \"^14.0.2\",\n \"depcheck\": \"^1.4.7\",\n \"fast-glob\": \"^3.3.3\",\n \"picocolors\": \"^1.1.1\",\n \"ts-morph\": \"^27.0.2\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.29.8\",\n \"@types/depcheck\": \"^0.9.0\",\n \"@types/glob\": \"^8.1.0\",\n \"@types/node\": \"^25.0.10\",\n \"eslint\": \"^9.39.2\",\n \"prettier\": \"^3.8.1\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.0.18\"\n }\n}\n","import path from \"path\";\n\nexport function getPackageSize(\n rootPath: string,\n pkg: string\n): string | undefined {\n try {\n const pkgJson = require(\n path.join(rootPath, \"node_modules\", pkg, \"package.json\")\n );\n if (typeof pkgJson.size === \"number\") {\n return `${(pkgJson.size / 1024).toFixed(2)} KB`;\n }\n } catch {}\n return undefined;\n}\n","import { Project, SyntaxKind, SourceFile } from \"ts-morph\";\nimport glob from \"fast-glob\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport pc from \"picocolors\";\nimport { AnalyzerOptions, UsageReport } from \"./types\";\n\nexport * from \"./types\";\n\nfunction getFolderSize(dirPath: string): number {\n let size = 0;\n try {\n const files = fs.readdirSync(dirPath);\n for (const file of files) {\n const filePath = path.join(dirPath, file);\n const stats = fs.statSync(filePath);\n if (stats.isDirectory()) size += getFolderSize(filePath);\n else size += stats.size;\n }\n } catch {}\n return size;\n}\n\nfunction formatBytes(bytes: number, decimals = 2) {\n if (bytes === 0) return \"0 Bytes\";\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + \" \" + sizes[i];\n}\n\nfunction getPackageSize(rootPath: string, packageName: string): string {\n const pkgPath = path.join(rootPath, \"node_modules\", packageName);\n if (fs.existsSync(pkgPath)) return formatBytes(getFolderSize(pkgPath));\n return \"N/A\";\n}\n\nexport async function analyzeProject(\n options: AnalyzerOptions\n): Promise<UsageReport> {\n const {\n rootPath,\n includeSizes = true,\n analyzeExports = true,\n silent = false\n } = options;\n\n if (!silent) {\n console.log(pc.green(`Analyzing project at ${rootPath}`));\n }\n\n // 1️⃣ Collect all JS/TS files\n const files = await glob(\"**/*.{js,jsx,ts,tsx}\", {\n cwd: rootPath,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/coverage/**\",\n \"**/*.config.{js,ts,cjs,mjs}\",\n \"**/*.d.ts\"\n ],\n absolute: true\n });\n\n if (!silent) {\n console.log(pc.blue(`Found ${files.length} files to analyze.`));\n }\n\n const project = new Project({ skipAddingFilesFromTsConfig: true });\n const tsConfigPath = path.join(rootPath, \"tsconfig.json\");\n if (fs.existsSync(tsConfigPath)) {\n project.addSourceFilesFromTsConfig(tsConfigPath);\n }\n files.forEach((f) => {\n try {\n project.addSourceFileAtPath(f);\n } catch {\n console.warn(pc.yellow(`Skipping ${f}`));\n }\n });\n\n // 2️⃣ Track package usage and file exports\n const packageUsage: Record<string, number> = {};\n const fileExports: Record<string, { named: Set<string>; default: boolean }> =\n {};\n const usedExports: Record<string, Set<string>> = {};\n const sourceFiles: Record<string, SourceFile> = {};\n\n for (const sourceFile of project.getSourceFiles()) {\n const relativePath = path\n .relative(rootPath, sourceFile.getFilePath())\n .replace(/\\\\/g, \"/\");\n sourceFiles[relativePath] = sourceFile;\n\n const exportsMap = sourceFile.getExportedDeclarations();\n const namedExports = new Set<string>();\n exportsMap.forEach((decls, name) => {\n if (name !== \"default\") namedExports.add(name);\n });\n const hasDefault = exportsMap.has(\"default\");\n\n fileExports[relativePath] = { named: namedExports, default: hasDefault };\n usedExports[relativePath] = new Set();\n\n // Track package imports\n const imports = sourceFile.getImportDeclarations();\n imports.forEach((imp) => {\n const mod = imp.getModuleSpecifierValue();\n if (!mod.startsWith(\".\") && !mod.startsWith(\"/\")) {\n const pkg = mod.startsWith(\"@\")\n ? mod.split(\"/\").slice(0, 2).join(\"/\")\n : mod.split(\"/\")[0];\n packageUsage[pkg] = (packageUsage[pkg] || 0) + 1;\n }\n });\n\n // Track require()\n const calls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);\n calls.forEach((call) => {\n if (call.getExpression().getText() === \"require\") {\n const args = call.getArguments();\n if (args.length && args[0].getKind() === SyntaxKind.StringLiteral) {\n const mod = args[0].getText().replace(/['\"`]/g, \"\");\n if (!mod.startsWith(\".\") && !mod.startsWith(\"/\")) {\n const pkg = mod.startsWith(\"@\")\n ? mod.split(\"/\").slice(0, 2).join(\"/\")\n : mod.split(\"/\")[0];\n packageUsage[pkg] = (packageUsage[pkg] || 0) + 1;\n }\n }\n }\n });\n }\n\n // 3️⃣ Track used exports across files\n if (analyzeExports) {\n for (const sourceFile of project.getSourceFiles()) {\n const imports = sourceFile.getImportDeclarations();\n const relativePath = path\n .relative(rootPath, sourceFile.getFilePath())\n .replace(/\\\\/g, \"/\");\n\n imports.forEach((imp) => {\n const mod = imp.getModuleSpecifierValue();\n if (mod.startsWith(\".\") || mod.startsWith(\"/\")) {\n const sourceDir = path.dirname(sourceFile.getFilePath());\n let resolvedPath = path.resolve(sourceDir, mod);\n const extensions = [\n \"\",\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \"/index.ts\",\n \"/index.tsx\",\n \"/index.js\",\n \"/index.jsx\"\n ];\n let foundFile: string | undefined;\n\n for (const ext of extensions) {\n const tryPath = path\n .relative(rootPath, resolvedPath + ext)\n .replace(/\\\\/g, \"/\");\n if (fileExports[tryPath]) {\n foundFile = tryPath;\n break;\n }\n }\n\n if (foundFile) {\n imp\n .getNamedImports()\n .forEach((ni) => usedExports[foundFile].add(ni.getName()));\n if (imp.getDefaultImport()) usedExports[foundFile].add(\"default\");\n }\n }\n });\n }\n }\n\n // 4️⃣ Determine unused files and exports\n const unusedFiles = Object.entries(fileExports)\n .filter(([file, exports]) => {\n if (\n file.includes(\"pages/\") ||\n file.includes(\"app/\") ||\n file.endsWith(\"index.tsx\") ||\n file.endsWith(\"App.tsx\")\n )\n return false;\n const used = usedExports[file];\n if (exports.named.size === 0 && !exports.default) return false;\n return used.size === 0;\n })\n .map(([file]) => file);\n\n const unusedExports: Record<string, string[]> = {};\n if (analyzeExports) {\n Object.entries(fileExports).forEach(([file, exports]) => {\n const used = usedExports[file];\n const unused: string[] = [];\n if (exports.default && !used.has(\"default\")) unused.push(\"default\");\n exports.named.forEach((name) => {\n if (!used.has(name)) unused.push(name);\n });\n if (unused.length) unusedExports[file] = unused;\n });\n }\n\n // 5️⃣ Build package report\n const packages: Record<string, { count: number; size: string }> = {};\n Object.entries(packageUsage).forEach(([pkg, count]) => {\n packages[pkg] = {\n count,\n size: includeSizes ? getPackageSize(rootPath, pkg) : \"—\"\n };\n });\n\n // 6️⃣ Run depcheck\n let unusedDependencies: string[] = [];\n try {\n const depcheck = require(\"depcheck\");\n // We can't easily wait for this if not async, but analyzeProject is async.\n const depcheckResult = await depcheck(rootPath, {\n ignoreMatches: [\"react-prune\", ...((options as any).ignoreMatches || [])],\n skipMissing: true\n });\n unusedDependencies = depcheckResult.dependencies;\n } catch (e) {\n if (!silent) console.warn(pc.yellow(\"Failed to run depcheck.\"));\n }\n\n return {\n packages,\n unusedFiles,\n unusedExports,\n usedExports,\n unusedDependencies,\n sourceFiles\n };\n}\n\nexport { getPackageSize };\n","import fs from \"fs\";\n\nexport function getFileSize(filePath: string): string {\n try {\n const stats = fs.statSync(filePath);\n const bytes = stats.size;\n if (bytes < 1024) return `${bytes} B`;\n return `${(bytes / 1024).toFixed(2)} KB`;\n } catch {\n return \"N/A\";\n }\n}\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport Table from \"cli-table3\";\nimport boxen from \"boxen\";\nimport path from \"path\";\nimport { analyzeProject, UsageReport } from \"./analyzer\";\nimport { getFileSize } from \"./analyzer/file-size\";\nimport { SyntaxKind, Identifier } from \"ts-morph\";\n\nconst program = new Command();\n\nprogram\n .name(\"react-prune\")\n .description(\"Analyze React/Next/Vite/React Native projects\")\n .version(require(\"../package.json\").version)\n .option(\"--no-size\", \"Skip package size calculation\")\n .option(\"--no-exports\", \"Skip export usage analysis\")\n .option(\"--limit <n>\", \"Limit output rows per table\", \"50\");\n\nprogram\n .command(\"analyze\")\n .description(\"Run full project analysis\")\n .option(\"--no-size\", \"Skip package size calculation\")\n .option(\"--no-exports\", \"Skip export usage analysis\")\n .option(\"--limit <n>\", \"Limit output rows per table\", \"50\")\n .option(\"--json\", \"Output results as JSON\")\n .action(async (opts) => {\n const rootPath = process.cwd();\n const limit = Number(opts.limit);\n\n const report: UsageReport = await analyzeProject({\n rootPath,\n includeSizes: opts.size,\n analyzeExports: opts.exports,\n silent: opts.json\n });\n\n if (opts.json) {\n // 1. Remove circular references (sourceFiles)\n // 2. Convert Sets to Arrays for valid JSON\n const { sourceFiles, usedExports, ...rest } = report;\n\n const sanitizedUsedExports: Record<string, string[]> = {};\n if (usedExports) {\n for (const [key, value] of Object.entries(usedExports)) {\n sanitizedUsedExports[key] = Array.from(value);\n }\n }\n\n console.log(\n JSON.stringify(\n {\n ...rest,\n usedExports: sanitizedUsedExports\n },\n null,\n 2\n )\n );\n return;\n }\n\n // Packages\n const packageTable = new Table({\n head: [pc.cyan(\"Package\"), \"Count\", \"Size\"],\n colWidths: [40, 10, 15]\n });\n Object.entries(report.packages)\n .sort((a, b) => b[1].count - a[1].count)\n .slice(0, limit)\n .forEach(([pkg, data]) =>\n packageTable.push([pkg, data.count, data.size])\n );\n console.log(\n boxen(pc.bold(\"📦 Package Usage\"), {\n padding: 1,\n borderColor: \"green\",\n borderStyle: \"round\"\n })\n );\n console.log(packageTable.toString());\n\n // Unused Files\n if (report.unusedFiles.length) {\n const table = new Table({\n head: [pc.yellow(\"Unused Files\")],\n colWidths: [80]\n });\n report.unusedFiles.slice(0, limit).forEach((f) => table.push([f]));\n console.log(\n boxen(pc.bold(`⚠️ Unused Files (${report.unusedFiles.length})`), {\n padding: 1,\n borderColor: \"yellow\",\n borderStyle: \"round\"\n })\n );\n console.log(table.toString());\n }\n\n // Unused Exports\n if (opts.exports) {\n const entries = Object.entries(report.unusedExports);\n if (entries.length) {\n const table = new Table({\n head: [\"File\", \"Unused Exports\"],\n colWidths: [50, 40],\n wordWrap: true\n });\n entries\n .slice(0, limit)\n .forEach(([file, exports]) => table.push([file, exports.join(\", \")]));\n console.log(\n boxen(pc.bold(`⚠️ Unused Exports`), {\n padding: 1,\n borderColor: \"yellow\",\n borderStyle: \"round\"\n })\n );\n console.log(table.toString());\n }\n }\n\n // Unused Dependencies\n if (report.unusedDependencies && report.unusedDependencies.length) {\n const table = new Table({\n head: [pc.yellow(\"Unused Dependencies\")],\n colWidths: [80]\n });\n report.unusedDependencies.slice(0, limit).forEach((d) => table.push([d]));\n console.log(\n boxen(\n pc.bold(\n `⚠️ Unused Dependencies (${report.unusedDependencies.length})`\n ),\n {\n padding: 1,\n borderColor: \"yellow\",\n borderStyle: \"round\"\n }\n )\n );\n console.log(table.toString());\n }\n });\n\nprogram\n .command(\"size <packageName>\")\n .description(\"Check the size of a specific npm package in node_modules\")\n .action(async (packageName) => {\n const rootPath = process.cwd();\n\n // Reuse helper from analyzer\n const { getPackageSize } = await import(\"./analyzer/package-size\");\n\n const size = getPackageSize(rootPath, packageName);\n\n if (size === \"N/A\") {\n console.log(\n pc.yellow(`Package '${packageName}' not found in node_modules.`)\n );\n } else {\n console.log(pc.green(`📦 ${packageName} size: ${size}`));\n }\n });\n// --- New find command with line numbers\nprogram\n .command(\"find <exportName>\")\n .description(\n \"Find usage count and references (with line numbers) for a component/function/export\"\n )\n .action(async (exportName) => {\n const rootPath = process.cwd();\n const report: UsageReport = await analyzeProject({\n rootPath,\n analyzeExports: true,\n includeSizes: false\n });\n\n const usageDetails: { file: string; line: number }[] = [];\n\n const usedExports = report.usedExports || {};\n\n for (const [file, usedSet] of Object.entries(usedExports)) {\n const sourceFile = report.sourceFiles?.[file];\n if (!sourceFile) continue;\n\n // Only process if this file actually uses the export\n if (!usedSet.has(exportName)) continue;\n\n // Traverse identifiers in the file\n const identifiers = sourceFile.getDescendantsOfKind(\n SyntaxKind.Identifier\n );\n\n identifiers.forEach((id: Identifier) => {\n // Check if identifier matches the export name\n if (id.getText() === exportName) {\n // Make sure this usage is actually an import/reference, not a declaration\n const parentKind = id.getParentOrThrow().getKindName();\n\n if (\n parentKind.includes(\"Import\") || // ImportSpecifier, ImportClause, etc\n parentKind.includes(\"PropertyAccess\") || // obj.exportName\n parentKind.includes(\"Identifier\") // usage in code\n ) {\n usageDetails.push({ file, line: id.getStartLineNumber() });\n }\n }\n });\n }\n\n if (usageDetails.length) {\n console.log(\n pc.green(`'${exportName}' is used ${usageDetails.length} time(s):`)\n );\n usageDetails.forEach((d) => {\n const size = getFileSize(path.join(rootPath, d.file));\n console.log(` - ${d.file}:${d.line} (${size})`);\n });\n } else {\n console.log(pc.yellow(`'${exportName}' is not used anywhere.`));\n }\n });\n\nprogram.parse(process.argv);\n"]}
|