From 7a63885d384e71001f2cca932e273050a0919b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl-Gerhard=20Lindesva=CC=88rd?= Date: Thu, 16 Oct 2025 13:14:43 +0200 Subject: [PATCH] fix: remove unused --- package.json | 3 +- tooling/unused-deps.mjs | 201 ---------------------------------------- 2 files changed, 1 insertion(+), 203 deletions(-) delete mode 100644 tooling/unused-deps.mjs diff --git a/package.json b/package.json index a9f725d5..2489eb4c 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,7 @@ "lint:fix": "biome check --write .", "lint:workspace": "pnpm dlx sherif@latest", "typecheck": "pnpm -r typecheck", - "update-simple-git-hooks": "npx simple-git-hooks", - "deps:unused": "node tooling/unused-deps.mjs" + "update-simple-git-hooks": "npx simple-git-hooks" }, "simple-git-hooks": { "pre-push": "pnpm typecheck && pnpm test" diff --git a/tooling/unused-deps.mjs b/tooling/unused-deps.mjs deleted file mode 100644 index 0db9793b..00000000 --- a/tooling/unused-deps.mjs +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env node - -import { spawn } from 'node:child_process'; -import { promises as fs } from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; - -// Lazy import depcheck to avoid hard crash if not installed -async function loadDepcheck() { - try { - const mod = await import('depcheck'); - return mod.default ?? mod; - } catch (err) { - console.error( - 'depcheck is not installed. Install it with: pnpm -w add -D depcheck', - ); - process.exitCode = 1; - process.exit(1); - } -} - -const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); -const repoRoot = path.resolve(__dirname, '..'); - -const DEFAULT_IGNORE_DIRS = [ - 'node_modules', - 'dist', - 'build', - '.next', - '.nuxt', - '.svelte-kit', - '.output', - '.turbo', - 'coverage', - '.vercel', - '.cache', - '.astro', - '.pnpm', -]; - -function parseArgs() { - const args = new Set(process.argv.slice(2)); - return { - json: args.has('--json') || args.has('-j'), - }; -} - -async function fileExists(p) { - try { - await fs.access(p); - return true; - } catch { - return false; - } -} - -async function readWorkspacePatterns() { - const workspaceFile = path.join(repoRoot, 'pnpm-workspace.yaml'); - if (!(await fileExists(workspaceFile))) return []; - const content = await fs.readFile(workspaceFile, 'utf8'); - const patterns = []; - for (const line of content.split(/\r?\n/)) { - const m = line.match(/^\s*-\s*"?([^"#]+)"?\s*(?:#.*)?$/); - if (m) { - patterns.push(m[1].trim()); - } - } - return patterns.filter(Boolean); -} - -async function isPackageDir(dir) { - const pkgPath = path.join(dir, 'package.json'); - return fileExists(pkgPath); -} - -async function listSubdirs(dir) { - const entries = await fs.readdir(dir, { withFileTypes: true }); - return entries - .filter((e) => e.isDirectory()) - .map((e) => path.join(dir, e.name)); -} - -async function findPackagesFromPattern(pattern) { - // Normalize pattern relative to repo root - const absolutePattern = path.resolve(repoRoot, pattern); - if (pattern.endsWith('/**')) { - const baseDir = absolutePattern.slice(0, -3); // remove /** - return await findPackagesRecursively(baseDir); - } - if (pattern.endsWith('/*')) { - const baseDir = absolutePattern.slice(0, -2); // remove /* - return (await listSubdirs(baseDir)).filterAsync(isPackageDir); - } - // Direct path - return (await isPackageDir(absolutePattern)) ? [absolutePattern] : []; -} - -async function findPackagesRecursively(startDir) { - const results = []; - async function walk(dir) { - if (!(await fileExists(dir))) return; - if (await isPackageDir(dir)) results.push(dir); - const subdirs = await listSubdirs(dir); - for (const sub of subdirs) { - await walk(sub); - } - } - await walk(startDir); - return results; -} - -// Add filterAsync utility on arrays -Object.defineProperty(Array.prototype, 'filterAsync', { - value: async function (predicate) { - const results = await Promise.all(this.map(predicate)); - return this.filter((_, i) => results[i]); - }, - enumerable: false, -}); - -async function discoverWorkspacePackageDirs() { - const patterns = await readWorkspacePatterns(); - const discovered = new Set(); - for (const pattern of patterns) { - const pkgs = await findPackagesFromPattern(pattern); - for (const p of pkgs) discovered.add(path.resolve(p)); - } - // Always include repo root as well - discovered.add(repoRoot); - return Array.from(discovered); -} - -async function runDepcheckOnDir(depcheck, dir) { - const result = await depcheck(dir, { - ignoreBinPackage: false, - ignoreDirs: DEFAULT_IGNORE_DIRS, - ignoreMatches: [], - specials: [ - depcheck.special.eslint, - depcheck.special.typescript, - depcheck.special.webpack, - depcheck.special.rollup, - depcheck.special.babel, - depcheck.special.postcss, - ], - }); - return { - dir, - unused: { - dependencies: result.dependencies ?? [], - devDependencies: result.devDependencies ?? [], - }, - }; -} - -function relative(p) { - return path.relative(repoRoot, p) || '.'; -} - -function printHuman(results) { - let any = false; - for (const { dir, unused } of results) { - if (unused.dependencies.length + unused.devDependencies.length === 0) - continue; - any = true; - console.log(`\n${relative(dir)}:`); - if (unused.dependencies.length) { - console.log(` unused dependencies (${unused.dependencies.length}):`); - for (const d of unused.dependencies) console.log(` - ${d}`); - } - if (unused.devDependencies.length) { - console.log( - ` unused devDependencies (${unused.devDependencies.length}):`, - ); - for (const d of unused.devDependencies) console.log(` - ${d}`); - } - } - if (!any) console.log('No unused dependencies found.'); -} - -async function main() { - const args = parseArgs(); - const depcheck = await loadDepcheck(); - const packageDirs = await discoverWorkspacePackageDirs(); - const checks = await Promise.all( - packageDirs.map((dir) => runDepcheckOnDir(depcheck, dir)), - ); - if (args.json) { - const compact = checks - .map(({ dir, unused }) => ({ dir: relative(dir), ...unused })) - .filter((r) => r.dependencies.length || r.devDependencies.length); - console.log(JSON.stringify(compact, null, 2)); - } else { - printHuman(checks); - } -} - -main().catch((err) => { - console.error(err); - process.exitCode = 1; -});