freshyo/scripts/dead-code/user-ui-symbols.js
2026-09-02 23:12:49 +05:30

62 lines
2 KiB
JavaScript

const fs = require('fs')
const path = require('path')
const { execSync } = require('child_process')
const ROOT = '/Users/mohammedshafiuddin/WebDev/freshyo'
const APP = 'apps/user-ui'
const files = execSync(
`find ${APP} -type f \\( -name '*.ts' -o -name '*.tsx' \\) -not -path '*/node_modules/*' -not -path '*/dist/*' -not -path '*/.expo/*' -not -path '*/.turbo/*'`,
{ cwd: ROOT }
).toString().trim().split('\n')
const codes = new Map()
for (const f of files) codes.set(f, fs.readFileSync(path.join(ROOT, f), 'utf8'))
function countWord(code, sym) {
const re = new RegExp(`\\b${sym.replace(/\$/g, '\\$')}\\b`, 'g')
return (code.match(re) || []).length
}
function exportedNames(code) {
const names = new Set()
let m
const pats = [
/export\s+(?:default\s+)?(?:async\s+)?function\s*\*?\s*(\w+)/g,
/export\s+(?:const|let|var)\s+(\w+)/g,
/export\s+(?:type|interface|class|enum)\s+(\w+)/g,
]
for (const p of pats) while ((m = p.exec(code))) names.add(m[1])
const br = /export\s*{([^}]*)}/g
while ((m = br.exec(code))) {
for (let part of m[1].split(',')) {
part = part.replace(/\/\/[^\n]*/g, '').trim().replace(/^type\s+/, '')
if (!part) continue
const asM = part.match(/\bas\s+(\w+)$/)
const nm = asM ? asM[1] : part.split(/\s/)[0]
if (/^[\w$]+$/.test(nm)) names.add(nm)
}
}
if (/export\s+default\s+function/.test(code) || /export\s+default\s+\w+/.test(code)) names.add('__default__')
return [...names]
}
console.log('=== UNUSED EXPORTS per file (symbol not referenced in any OTHER user-ui file) ===')
for (const [f, code] of codes) {
if (f.startsWith(`${APP}/app/`)) continue // routes
const names = exportedNames(code)
const unused = []
for (const sym of names) {
if (sym === '__default__') continue
let refs = 0
for (const [of, oc] of codes) {
if (of === f) continue
refs += countWord(oc, sym)
}
if (refs === 0) unused.push(sym)
}
if (unused.length) {
console.log(`\n${f.replace(APP + '/', '')}`)
console.log(' ' + unused.join(', '))
}
}