Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  repo-scan.ts   Sprache: unbekannt

 
import fs from "node:fs/promises";
import path from "node:path";

export const DEFAULT_REPO_SCAN_SKIP_DIR_NAMES = new Set([".git""dist""node_modules"]);
export const DEFAULT_RUNTIME_SOURCE_ROOTS = ["src""extensions"] as const;
export const DEFAULT_RUNTIME_SOURCE_EXTENSIONS = [".ts"".tsx"] as const;
export const RUNTIME_SOURCE_SKIP_PATTERNS = [
  /\.test\.tsx?$/,
  /\.test-helpers\.tsx?$/,
  /\.test-utils\.tsx?$/,
  /\.e2e\.tsx?$/,
  /\.d\.ts$/,
  /\/(?:__tests__|tests)\//,
  /\/[^/]*test-helpers(?:\.[^/]+)?\.tsx?$/,
  /\/[^/]*test-utils(?:\.[^/]+)?\.tsx?$/,
] as const;

export type RepoFileScanOptions = {
  roots: readonly string[];
  extensions: readonly string[];
  skipDirNames?: ReadonlySet<string>;
  skipHiddenDirectories?: boolean;
  shouldIncludeFile?: (relativePath: string) => boolean;
};
export type RuntimeSourceScanOptions = {
  roots?: readonly string[];
  extensions?: readonly string[];
};

type PendingDir = {
  absolutePath: string;
};
const runtimeSourceScanCache = new Map<string, Promise<Array<string>>>();

function shouldSkipDirectory(
  name: string,
  options: Pick<RepoFileScanOptions, "skipDirNames" | "skipHiddenDirectories">,
): boolean {
  if (options.skipHiddenDirectories && name.startsWith(".")) {
    return true;
  }
  return (options.skipDirNames ?? DEFAULT_REPO_SCAN_SKIP_DIR_NAMES).has(name);
}

function hasAllowedExtension(fileName: string, extensions: readonly string[]): boolean {
  return extensions.some((extension) => fileName.endsWith(extension));
}

function normalizeRelativePath(relativePath: string): string {
  return relativePath.replaceAll("\\""/");
}

function toSortedUnique(values: readonly string[]): Array<string> {
  return [...new Set(values)].toSorted();
}

function getRuntimeScanCacheKey(repoRoot: string, roots: readonly string[]): string {
  return `${repoRoot}::${toSortedUnique(roots).join(",")}`;
}

export async function listRepoFiles(
  repoRoot: string,
  options: RepoFileScanOptions,
): Promise<Array<string>> {
  const files: Array<string> = [];
  const pending: Array<PendingDir> = [];

  for (const root of options.roots) {
    const absolutePath = path.join(repoRoot, root);
    try {
      const stats = await fs.stat(absolutePath);
      if (stats.isDirectory()) {
        pending.push({ absolutePath });
      }
    } catch {
      // Skip missing roots. Useful when the bundled plugin tree is absent.
    }
  }

  while (pending.length > 0) {
    const current = pending.pop();
    if (!current) {
      continue;
    }
    const entries = await fs.readdir(current.absolutePath, { withFileTypes: true });
    for (const entry of entries) {
      if (entry.isDirectory()) {
        if (!shouldSkipDirectory(entry.name, options)) {
          pending.push({ absolutePath: path.join(current.absolutePath, entry.name) });
        }
        continue;
      }
      if (!entry.isFile() || !hasAllowedExtension(entry.name, options.extensions)) {
        continue;
      }
      const filePath = path.join(current.absolutePath, entry.name);
      const relativePath = path.relative(repoRoot, filePath);
      if (options.shouldIncludeFile && !options.shouldIncludeFile(relativePath)) {
        continue;
      }
      files.push(filePath);
    }
  }

  files.sort((a, b) => a.localeCompare(b));
  return files;
}

export function shouldSkipRuntimeSourcePath(relativePath: string): boolean {
  const normalizedPath = normalizeRelativePath(relativePath);
  return RUNTIME_SOURCE_SKIP_PATTERNS.some((pattern) => pattern.test(normalizedPath));
}

export async function listRuntimeSourceFiles(
  repoRoot: string,
  options: RuntimeSourceScanOptions = {},
): Promise<Array<string>> {
  const roots = options.roots ?? DEFAULT_RUNTIME_SOURCE_ROOTS;
  const requestedExtensions = toSortedUnique(
    options.extensions ?? DEFAULT_RUNTIME_SOURCE_EXTENSIONS,
  );
  const cacheKey = getRuntimeScanCacheKey(repoRoot, roots);

  let pending = runtimeSourceScanCache.get(cacheKey);
  if (!pending) {
    pending = listRepoFiles(repoRoot, {
      roots,
      extensions: DEFAULT_RUNTIME_SOURCE_EXTENSIONS,
      skipHiddenDirectories: true,
      shouldIncludeFile: (relativePath) => !shouldSkipRuntimeSourcePath(relativePath),
    });
    runtimeSourceScanCache.set(cacheKey, pending);
  }
  const files = await pending;
  return files.filter((filePath) =>
    requestedExtensions.some((extension) => filePath.endsWith(extension)),
  );
}

Messung V0.5 in Prozent
C=99 H=92 G=95

[zur Elbe Produktseite wechseln0.14QuellennavigatorsAnalyse erneut starten2026-06-09]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002