pruny 1.44.3 → 1.44.5

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 +59 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14198,7 +14198,7 @@ function getAppName(filePath) {
14198
14198
  }
14199
14199
  function makeCodePattern(name) {
14200
14200
  const escaped = escapeRegExp(name);
14201
- return new RegExp(`\\b${escaped}\\s*[({.,;<>|&\\[=)]` + `|\\b${escaped}\\s*\\)` + `|\\.[\\s\\n]*${escaped}\\b` + `|\\b${escaped}\\s*:[^:]` + `|:\\s*${escaped}\\b`);
14201
+ return new RegExp(`\\b${escaped}\\s*[({.,;<>|&\\[=)]` + `|\\b${escaped}\\s*\\)` + `|\\.[\\s\\n]*${escaped}\\b` + `|\\b${escaped}\\s*:[^:]` + `|:\\s*${escaped}\\b` + `|<\\/?${escaped}(?=[\\s/>]|$)`);
14202
14202
  }
14203
14203
  function escapeRegExp(string) {
14204
14204
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -14964,7 +14964,6 @@ async function scanUnusedExports(config, routes = [], options = {}) {
14964
14964
  console.log(`[DEBUG USE] ${exp.name} used internally in ${file} at line ${i + 1}: ${line.trim()}`);
14965
14965
  }
14966
14966
  usedInternally = true;
14967
- isUsed = true;
14968
14967
  break;
14969
14968
  }
14970
14969
  }
@@ -14985,6 +14984,10 @@ async function scanUnusedExports(config, routes = [], options = {}) {
14985
14984
  const absoluteOtherFileFixed = isAbsolute2(otherFile) ? otherFile : join4(scanCwd, otherFile);
14986
14985
  const hasIgnoreRanges = ignoreRanges.has(absoluteOtherFileFixed);
14987
14986
  const isGeneric = GENERIC_METHOD_NAMES.has(exp.name);
14987
+ const hasSelfImport = new RegExp(`import.*\\b${escapeRegExp(exp.name)}\\b.*from`).test(content);
14988
+ const hasSelfDecl = new RegExp(`(?:export\\s+)?(?:abstract\\s+)?(?:interface|class|enum)\\s+${escapeRegExp(exp.name)}\\b|` + `(?:export\\s+)?(?:async\\s+)?(?:function)\\s+${escapeRegExp(exp.name)}\\b|` + `(?:export\\s+)?(?:const|let|var|type)\\s+${escapeRegExp(exp.name)}\\s*[=<]`).test(content);
14989
+ if (hasSelfDecl && !hasSelfImport)
14990
+ continue;
14988
14991
  if (!hasIgnoreRanges && !isGeneric) {
14989
14992
  const jsxPattern = new RegExp(`<${exp.name}[\\s/>]`);
14990
14993
  if (jsxPattern.test(content)) {
@@ -15325,11 +15328,18 @@ function removeExportFromLine(rootDir, exp) {
15325
15328
  const content = readFileSync7(fullPath, "utf-8");
15326
15329
  const lines = content.split(`
15327
15330
  `);
15328
- const lineIndex = findDeclarationIndex(lines, exp.name, exp.line - 1);
15331
+ let lineIndex = findDeclarationIndex(lines, exp.name, exp.line - 1);
15332
+ if (lineIndex === -1) {
15333
+ lineIndex = findDeclarationIndex(lines, exp.name, 0);
15334
+ }
15329
15335
  if (!exp.usedInternally) {
15336
+ if (lineIndex === -1) {
15337
+ return removeFromBlockExport(lines, fullPath, exp.name, exp.line);
15338
+ }
15330
15339
  const trueStartLine = findDeclarationStart(lines, lineIndex);
15331
15340
  const deletedLines = deleteDeclaration(lines, trueStartLine, exp.name);
15332
15341
  if (deletedLines > 0) {
15342
+ removeFromBlockExport(lines, fullPath, exp.name, exp.line);
15333
15343
  const newContent = lines.join(`
15334
15344
  `);
15335
15345
  if (isFileEmpty(newContent)) {
@@ -15341,7 +15351,12 @@ function removeExportFromLine(rootDir, exp) {
15341
15351
  }
15342
15352
  return false;
15343
15353
  }
15354
+ if (lineIndex === -1) {
15355
+ return removeFromBlockExport(lines, fullPath, exp.name, exp.line);
15356
+ }
15344
15357
  const originalLine = lines[lineIndex];
15358
+ if (!originalLine)
15359
+ return false;
15345
15360
  if (originalLine.trim().startsWith("export ")) {
15346
15361
  const newLine = originalLine.replace(/(\s*)export\s+/, "$1");
15347
15362
  lines[lineIndex] = newLine;
@@ -15349,12 +15364,31 @@ function removeExportFromLine(rootDir, exp) {
15349
15364
  `), "utf-8");
15350
15365
  return true;
15351
15366
  }
15352
- return false;
15367
+ return removeFromBlockExport(lines, fullPath, exp.name, exp.line);
15353
15368
  } catch (err) {
15354
15369
  console.error(`Error fixing export in ${exp.file}:`, err);
15355
15370
  return false;
15356
15371
  }
15357
15372
  }
15373
+ function removeFromBlockExport(lines, fullPath, name, exportLine) {
15374
+ const lineIdx = exportLine - 1;
15375
+ const line = lines[lineIdx];
15376
+ if (!line)
15377
+ return false;
15378
+ if (!/^export\s*\{/.test(line.trim()))
15379
+ return false;
15380
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
15381
+ let newLine = line.replace(new RegExp(`\\b${escaped}\\b\\s*,\\s*`), "").replace(new RegExp(`,\\s*\\b${escaped}\\b`), "").replace(new RegExp(`\\b${escaped}\\b`), "");
15382
+ newLine = newLine.replace(/\{\s*\}/, "{}").replace(/\{\s+/, "{ ").replace(/\s+\}/, " }");
15383
+ if (newLine.trim() === "export {}" || newLine.trim() === "export { }") {
15384
+ lines.splice(lineIdx, 1);
15385
+ } else {
15386
+ lines[lineIdx] = newLine;
15387
+ }
15388
+ writeFileSync(fullPath, lines.join(`
15389
+ `), "utf-8");
15390
+ return true;
15391
+ }
15358
15392
  function findDeclarationIndex(lines, name, startLine = 0) {
15359
15393
  const methodRegex = new RegExp(`(?:public|private|protected|static|async|readonly)?\\s*(?:async)?\\s*${name}\\s*[(<]`);
15360
15394
  const declRegex = new RegExp(`(?:export\\s+)?(?:default\\s+)?(?:(?:abstract|async|static|readonly)\\s+)*(?:class|interface|type|enum|function|const|let|var)\\s+${name}\\b`);
@@ -15426,6 +15460,7 @@ function deleteDeclaration(lines, startLine, name) {
15426
15460
  return 0;
15427
15461
  let endLine = startLine;
15428
15462
  let braceCount = 0;
15463
+ let bracketCount = 0;
15429
15464
  let parenCount = 0;
15430
15465
  let foundMethodDefinition = false;
15431
15466
  let foundBodyOpening = false;
@@ -15446,6 +15481,16 @@ function deleteDeclaration(lines, startLine, name) {
15446
15481
  if (inTemplateLiteral) {
15447
15482
  if (backtickCount % 2 !== 0) {
15448
15483
  inTemplateLiteral = false;
15484
+ const lastTick = line.lastIndexOf("`");
15485
+ const afterTick = sanitizeLine(line.slice(lastTick + 1));
15486
+ const extraOpens = (afterTick.match(/{/g) || []).length;
15487
+ const extraCloses = (afterTick.match(/}/g) || []).length;
15488
+ braceCount += extraOpens - extraCloses;
15489
+ if (foundBodyOpening && braceCount <= 0 && bracketCount <= 0) {
15490
+ endLine = i;
15491
+ foundClosing = true;
15492
+ break;
15493
+ }
15449
15494
  }
15450
15495
  continue;
15451
15496
  }
@@ -15458,6 +15503,8 @@ function deleteDeclaration(lines, startLine, name) {
15458
15503
  const closeBraces = (cleanLine.match(/}/g) || []).length;
15459
15504
  const openParens = (cleanLine.match(/\(/g) || []).length;
15460
15505
  const closeParens = (cleanLine.match(/\)/g) || []).length;
15506
+ const openBrackets = (cleanLine.match(/\[/g) || []).length;
15507
+ const closeBrackets = (cleanLine.match(/\]/g) || []).length;
15461
15508
  if (!foundMethodDefinition) {
15462
15509
  if (isDecorator || currentDecoratorParenDepth > 0 || currentDecoratorBraceDepth > 0) {
15463
15510
  currentDecoratorParenDepth += openParens - closeParens;
@@ -15476,11 +15523,12 @@ function deleteDeclaration(lines, startLine, name) {
15476
15523
  }
15477
15524
  foundMethodDefinition = true;
15478
15525
  braceCount = openBraces - closeBraces;
15526
+ bracketCount = openBrackets - closeBrackets;
15479
15527
  parenCount = openParens - closeParens;
15480
- if (openBraces > 0 && parenCount === 0) {
15528
+ if ((openBraces > 0 || bracketCount > 0) && parenCount === 0) {
15481
15529
  foundBodyOpening = true;
15482
15530
  }
15483
- if (foundBodyOpening && braceCount <= 0) {
15531
+ if (foundBodyOpening && braceCount <= 0 && bracketCount <= 0) {
15484
15532
  endLine = i;
15485
15533
  foundClosing = true;
15486
15534
  break;
@@ -15489,11 +15537,12 @@ function deleteDeclaration(lines, startLine, name) {
15489
15537
  }
15490
15538
  } else {
15491
15539
  braceCount += openBraces - closeBraces;
15540
+ bracketCount += openBrackets - closeBrackets;
15492
15541
  parenCount += openParens - closeParens;
15493
- if (!foundBodyOpening && openBraces > 0 && parenCount === 0) {
15542
+ if (!foundBodyOpening && (openBraces > 0 || openBrackets > 0) && parenCount === 0) {
15494
15543
  foundBodyOpening = true;
15495
15544
  }
15496
- if (foundBodyOpening && braceCount <= 0) {
15545
+ if (foundBodyOpening && braceCount <= 0 && bracketCount <= 0) {
15497
15546
  endLine = i;
15498
15547
  foundClosing = true;
15499
15548
  break;
@@ -18372,6 +18421,8 @@ Analyzing cascading impact...`));
18372
18421
  result.used = result.routes.filter((r) => r.used).length;
18373
18422
  result.total = result.routes.length;
18374
18423
  }
18424
+ if (options.cleanup)
18425
+ return "exit";
18375
18426
  console.log("");
18376
18427
  continue;
18377
18428
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pruny",
3
- "version": "1.44.3",
3
+ "version": "1.44.5",
4
4
  "description": "Find and remove unused Next.js API routes & Nest.js Controllers",
5
5
  "type": "module",
6
6
  "files": [