hedidit
Version:
98 lines (97 loc) • 3.88 kB
JavaScript
import { readdir } from "node:fs/promises";
import { join } from "node:path";
import { parseGitIgnoreFile, shouldIgnore, CONFIG_FILE_CHECKS, DEP_TO_TECH_MAP, ORG_TO_TECH_MAP, capitalizeFirstLetter } from "./filter";
import { readFile, access } from "node:fs/promises";
import { constants } from "node:fs";
export async function buildFileTree(rootPath, currentPath, indent = "") {
let result = "";
const gitIgnoreRules = await parseGitIgnoreFile(rootPath);
const entries = await readdir(currentPath, { withFileTypes: true });
const sortedEntries = entries.sort((a, b) => {
if (a.isDirectory() && !b.isDirectory())
return -1;
if (!a.isDirectory() && b.isDirectory())
return 1;
return a.name.localeCompare(b.name);
});
for (let i = 0; i < sortedEntries.length; i++) {
const entry = sortedEntries[i];
const entryPath = join(currentPath, entry.name);
// Skip directories that are commonly ignored
if (entry.isDirectory() &&
(entry.name === "node_modules" ||
entry.name.startsWith('.') ||
entry.name === "dist" ||
entry.name === "build")) {
continue;
}
// Skip files and directories based on .gitignore rules
if (shouldIgnore(entryPath, rootPath, gitIgnoreRules)) {
continue;
}
const isLast = i === sortedEntries.length - 1;
const prefix = isLast ? "└── " : "├── ";
result += `${indent}${prefix}${entry.name}\n`;
if (entry.isDirectory()) {
const newIndent = indent + (isLast ? " " : "│ ");
result += await buildFileTree(rootPath, entryPath, newIndent);
}
}
return result;
}
export async function getTechStack(rootPath) {
const techStack = [];
// Check for config files to infer technologies
for (const { file, tech } of CONFIG_FILE_CHECKS) {
if (await fileExists(join(rootPath, file))) {
techStack.push(tech);
}
}
// If no TypeScript or JavaScript is detected yet, default to JavaScript
if (!techStack.includes('TypeScript') && !techStack.includes('JavaScript')) {
techStack.push('JavaScript');
}
// Parse package.json for dependencies
try {
const packageJsonPath = join(rootPath, 'package.json');
if (await fileExists(packageJsonPath)) {
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
const dependencies = packageJson.dependencies || {};
// Process dependencies
for (const [dep, version] of Object.entries(dependencies)) {
// Exact matches
if (DEP_TO_TECH_MAP[dep]) {
if (!techStack.includes(DEP_TO_TECH_MAP[dep])) {
techStack.push(DEP_TO_TECH_MAP[dep]);
}
continue;
}
// Handle scoped packages (@org/pkg) and patterns
if (dep.startsWith('@')) {
// Extract organization name
const orgName = dep.split('/')[0].slice(1);
if (ORG_TO_TECH_MAP[orgName] && !techStack.includes(ORG_TO_TECH_MAP[orgName])) {
techStack.push(ORG_TO_TECH_MAP[orgName]);
}
else {
techStack.push(capitalizeFirstLetter(orgName));
}
}
}
}
}
catch (error) {
console.error('Error parsing package.json:', error);
}
// Remove duplicates and return
return [...new Set(techStack)];
}
async function fileExists(filePath) {
try {
await access(filePath, constants.F_OK);
return true;
}
catch {
return false;
}
}