pruny 1.43.8 → 1.43.10

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.
Files changed (2) hide show
  1. package/dist/index.js +35 -16
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14255,7 +14255,7 @@ function parseTsConfigPaths(searchDir) {
14255
14255
  function readTsConfigWithExtends(configPath) {
14256
14256
  try {
14257
14257
  const raw = readFileSync2(configPath, "utf-8");
14258
- const cleaned = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/,(\s*[}\]])/g, "$1");
14258
+ const cleaned = raw.replace(/("(?:\\.|[^"\\])*")|\/\/.*$|\/\*[\s\S]*?\*\//gm, (_m, str) => str ?? "").replace(/,(\s*[}\]])/g, "$1");
14259
14259
  const config = JSON.parse(cleaned);
14260
14260
  let basePaths = {};
14261
14261
  let baseUrl;
@@ -14290,7 +14290,7 @@ async function scanUnusedFiles(config) {
14290
14290
  process.stdout.write(` \uD83D\uDCC2 Scanning source files...`);
14291
14291
  const allFiles = await import_fast_glob2.default(extGlob, {
14292
14292
  cwd: searchDir,
14293
- ignore: [...config.ignore.folders, ...config.ignore.files],
14293
+ ignore: config.ignore.folders,
14294
14294
  absolute: true
14295
14295
  });
14296
14296
  process.stdout.write(` ${allFiles.length} files found
@@ -14299,6 +14299,15 @@ async function scanUnusedFiles(config) {
14299
14299
  return { total: 0, used: 0, unused: 0, files: [] };
14300
14300
  }
14301
14301
  const allFilesSet = new Set(allFiles);
14302
+ const ignoredFileSet = new Set;
14303
+ if (config.ignore.files.length > 0) {
14304
+ for (const file of allFiles) {
14305
+ const relPath = relative(searchDir, file);
14306
+ if (config.ignore.files.some((pattern) => minimatch(relPath, pattern, { dot: true }))) {
14307
+ ignoredFileSet.add(file);
14308
+ }
14309
+ }
14310
+ }
14302
14311
  const entryFiles = new Set;
14303
14312
  const entryPatterns = [
14304
14313
  "**/page.{ts,tsx,js,jsx}",
@@ -14367,6 +14376,8 @@ async function scanUnusedFiles(config) {
14367
14376
  if (isEntry)
14368
14377
  entryFiles.add(file);
14369
14378
  }
14379
+ for (const file of ignoredFileSet)
14380
+ entryFiles.add(file);
14370
14381
  const aliasMap = parseTsConfigPaths(searchDir);
14371
14382
  if (process.env.DEBUG_PRUNY && aliasMap.size > 0) {
14372
14383
  console.log(`[DEBUG] Loaded ${aliasMap.size} path aliases from tsconfig.json`);
@@ -14418,16 +14429,18 @@ async function scanUnusedFiles(config) {
14418
14429
  }
14419
14430
  } catch {}
14420
14431
  }
14421
- const files = allFiles.filter((f) => !usedFiles.has(f)).map((f) => {
14432
+ const files = allFiles.filter((f) => !usedFiles.has(f) && !ignoredFileSet.has(f)).map((f) => {
14422
14433
  const s = statSync(f);
14423
14434
  return {
14424
14435
  path: relative(config.dir, f),
14425
14436
  size: s.size
14426
14437
  };
14427
14438
  });
14439
+ const candidateCount = allFiles.length - ignoredFileSet.size;
14440
+ const usedCandidateCount = candidateCount - files.length;
14428
14441
  return {
14429
- total: allFiles.length,
14430
- used: usedFiles.size,
14442
+ total: candidateCount,
14443
+ used: usedCandidateCount,
14431
14444
  unused: files.length,
14432
14445
  files
14433
14446
  };
@@ -14731,7 +14744,7 @@ async function scanUnusedExports(config, routes = [], options = {}) {
14731
14744
  }
14732
14745
  const referenceFiles = await import_fast_glob3.default(extGlob, {
14733
14746
  cwd: referenceCwd,
14734
- ignore: [...DEFAULT_IGNORE, ...config.ignore.folders, ...config.ignore.files],
14747
+ ignore: [...DEFAULT_IGNORE, ...config.ignore.folders],
14735
14748
  absolute: true
14736
14749
  });
14737
14750
  if (process.env.DEBUG_PRUNY) {
@@ -15876,13 +15889,13 @@ var import_fast_glob9 = __toESM(require_out4(), 1);
15876
15889
  import { readFileSync as readFileSync9, existsSync as existsSync7 } from "node:fs";
15877
15890
  import { join as join7 } from "node:path";
15878
15891
  var LINK_PATTERNS = [
15879
- /<Link\s+[^>]*href\s*=\s*['"`](\/[^'"`\s{}$]+)['"`]/g,
15880
- /router\.(push|replace)\s*\(\s*['"`](\/[^'"`\s{}$]+)['"`]/g,
15881
- /(?:redirect|permanentRedirect)\s*\(\s*['"`](\/[^'"`\s{}$]+)['"`]/g,
15882
- /href\s*:\s*['"`](\/[^'"`\s{}$]+)['"`]/g,
15883
- /<a\s+[^>]*href\s*=\s*['"`](\/[^'"`\s{}$]+)['"`]/g,
15884
- /revalidatePath\s*\(\s*['"`](\/[^'"`\s{}$]+)['"`]/g,
15885
- /pathname\s*===?\s*['"`](\/[^'"`\s{}$]+)['"`]/g
15892
+ /<Link\s+[^>]*href\s*=\s*(?:\{\s*)?['"`](\/[^'"`\s]+)['"`](?:\s*\})?/g,
15893
+ /router\.(push|replace)\s*\(\s*['"`](\/[^'"`\s]+)['"`]/g,
15894
+ /(?:redirect|permanentRedirect)\s*\(\s*['"`](\/[^'"`\s]+)['"`]/g,
15895
+ /href\s*:\s*['"`](\/[^'"`\s]+)['"`]/g,
15896
+ /<a\s+[^>]*href\s*=\s*(?:\{\s*)?['"`](\/[^'"`\s]+)['"`](?:\s*\})?/g,
15897
+ /revalidatePath\s*\(\s*['"`](\/[^'"`\s]+)['"`]/g,
15898
+ /pathname\s*===?\s*['"`](\/[^'"`\s]+)['"`]/g
15886
15899
  ];
15887
15900
  function extractPath(match2) {
15888
15901
  if (match2[2] && match2[2].startsWith("/"))
@@ -15891,6 +15904,11 @@ function extractPath(match2) {
15891
15904
  return match2[1];
15892
15905
  return null;
15893
15906
  }
15907
+ function normalizePath(raw) {
15908
+ let out = raw.replace(/\$\{[^}]*\}/g, "[id]");
15909
+ out = out.replace(/[{}]/g, "");
15910
+ return out;
15911
+ }
15894
15912
  function shouldSkipPath(path2) {
15895
15913
  if (/^https?:\/\//.test(path2))
15896
15914
  return true;
@@ -15984,7 +16002,7 @@ function isGitignoredPublicFile(appDir, linkPath) {
15984
16002
  continue;
15985
16003
  try {
15986
16004
  const patterns = readFileSync9(gitignorePath, "utf-8").split(`
15987
- `).map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
16005
+ `).map((l) => l.trim()).filter((l) => l && !l.startsWith("#") && !l.startsWith("!"));
15988
16006
  for (const pattern of patterns) {
15989
16007
  if (minimatch(publicRelPath, pattern, { dot: true }) || minimatch(linkPath.slice(1), pattern, { dot: true }) || minimatch(`**/public${linkPath}`, pattern, { dot: true })) {
15990
16008
  return true;
@@ -16060,9 +16078,10 @@ async function scanBrokenLinks(config) {
16060
16078
  pattern.lastIndex = 0;
16061
16079
  let match2;
16062
16080
  while ((match2 = pattern.exec(content)) !== null) {
16063
- const rawPath = extractPath(match2);
16064
- if (!rawPath)
16081
+ const extracted = extractPath(match2);
16082
+ if (!extracted)
16065
16083
  continue;
16084
+ const rawPath = normalizePath(extracted);
16066
16085
  if (shouldSkipPath(rawPath))
16067
16086
  continue;
16068
16087
  const cleaned = cleanPath(rawPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pruny",
3
- "version": "1.43.8",
3
+ "version": "1.43.10",
4
4
  "description": "Find and remove unused Next.js API routes & Nest.js Controllers",
5
5
  "type": "module",
6
6
  "files": [