All files discovery.ts

97.56% Statements 40/41
95.45% Branches 21/22
100% Functions 4/4
100% Lines 31/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80                  10x   15x 22x     36x 35x   34x   5x 5x     29x 29x   28x 28x 25x   22x       10x 10x         3x   2x         6x   5x 10x 5x   5x   10x 10x 10x   9x 9x   7x             5x       5x          
import fs from 'node:fs';
import path from 'node:path';
 
import { ALLOWED_EXTS } from './types.js';
import { isTestFile } from './utils.js';
 
import type { AnalysisOptions, FileEntry, PackageInfo } from './types.js';
 
export function collectFiles(rootDir: string, opts: AnalysisOptions): string[] {
  const files: string[] = [];
  const walk = (dir: string): void => {
    const entries = fs.readdirSync(dir, { withFileTypes: true });
    entries.sort((a, b) => a.name.localeCompare(b.name));
 
    for (const entry of entries) {
      if (opts.ignoreDirs.has(entry.name)) continue;
      if (entry.isSymbolicLink()) continue;
 
      const next = path.join(dir, entry.name);
      if (entry.isDirectory()) {
        walk(next);
        continue;
      }
 
      Iif (!entry.isFile()) continue;
      if (entry.name.endsWith('.d.ts')) continue;
 
      const ext = path.extname(entry.name);
      if (!ALLOWED_EXTS.has(ext)) continue;
      if (!opts.includeTests && isTestFile(next)) continue;
 
      files.push(next);
    }
  };
 
  walk(rootDir);
  return files;
}
 
export function safeRead(filePath: string): string | null {
  try {
    return fs.readFileSync(filePath, 'utf8');
  } catch {
    return null;
  }
}
 
export function listWorkspacePackages(root: string, packageRoot: string): PackageInfo[] {
  if (!fs.existsSync(packageRoot) || !fs.statSync(packageRoot).isDirectory()) return [];
 
  const packageDirs = fs.readdirSync(packageRoot, { withFileTypes: true })
    .filter((entry) => entry.isDirectory())
    .sort((a, b) => a.name.localeCompare(b.name));
 
  const packages: PackageInfo[] = [];
  for (const entry of packageDirs) {
    const dir = path.join(packageRoot, entry.name);
    const manifest = path.join(dir, 'package.json');
    if (!fs.existsSync(manifest)) continue;
 
    try {
      const json = JSON.parse(fs.readFileSync(manifest, 'utf8'));
      if (typeof json.name === 'string') {
        packages.push({ name: json.name, dir, folder: entry.name });
      }
    } catch {
      // Ignore invalid package manifests.
    }
  }
 
  return packages;
}
 
export function fileSummaryWithFindings(fileSummaries: FileEntry[], byFile: Map<string, string[]>): (FileEntry & { issueIds: string[] })[] {
  return fileSummaries.map((entry) => ({
    ...entry,
    issueIds: byFile.get(entry.file) || [],
  }));
}