124 lines
3.4 KiB
JavaScript
124 lines
3.4 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
// Add type module declaration at the top
|
|
// @ts-check
|
|
// @ts-ignore
|
|
// eslint-disable-next-line
|
|
// @ts-nocheck
|
|
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import { fileURLToPath } from "url";
|
|
import { dirname } from "path";
|
|
import { isIgnored } from "isomorphic-git";
|
|
|
|
// Setup ESM compatibility
|
|
// const __filename = fileURLToPath(import.meta.url);
|
|
// const __dirname = dirname(__filename);
|
|
|
|
// File extensions to include
|
|
const ALLOWED_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".css"];
|
|
|
|
// Function to check if a path is ignored by gitignore
|
|
async function isGitIgnored(
|
|
filePath: string,
|
|
baseDir: string
|
|
): Promise<boolean> {
|
|
try {
|
|
const relativePath = path.relative(baseDir, filePath);
|
|
return await isIgnored({ fs, dir: baseDir, filepath: relativePath });
|
|
} catch (error) {
|
|
console.error(`Error checking if path is git ignored: ${filePath}`, error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Function to recursively walk a directory
|
|
async function walkDirectory(dir: string, baseDir: string): Promise<string[]> {
|
|
const files: string[] = [];
|
|
|
|
// Read directory contents
|
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
|
|
for (const entry of entries) {
|
|
const fullPath = path.join(dir, entry.name);
|
|
|
|
// Skip if the entry is git ignored
|
|
if (await isGitIgnored(fullPath, baseDir)) {
|
|
continue;
|
|
}
|
|
|
|
if (entry.isDirectory()) {
|
|
// Recursively process subdirectories
|
|
const subDirFiles = await walkDirectory(fullPath, baseDir);
|
|
files.push(...subDirFiles);
|
|
} else if (entry.isFile()) {
|
|
// Check file extension
|
|
const ext = path.extname(entry.name).toLowerCase();
|
|
if (ALLOWED_EXTENSIONS.includes(ext)) {
|
|
files.push(fullPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
// Function to read file contents and format for LLM consumption
|
|
function formatFile(filePath: string, baseDir: string): string {
|
|
try {
|
|
const relativePath = path.relative(baseDir, filePath);
|
|
|
|
// Check if the file is in components/ui directory
|
|
if (
|
|
relativePath.includes("eslint.config") ||
|
|
relativePath.includes("components/ui") ||
|
|
relativePath.includes("components\\ui")
|
|
) {
|
|
return `## File: ${relativePath}\n\n`;
|
|
}
|
|
|
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
|
|
return `## File: ${relativePath}\n\`\`\`${path
|
|
.extname(filePath)
|
|
.substring(1)}\n${content}\n\`\`\`\n\n`;
|
|
} catch (error) {
|
|
console.error(`Error reading file: ${filePath}`, error);
|
|
return `## File: ${filePath}\nError reading file: ${error}\n\n`;
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
// Get command line arguments
|
|
const args = process.argv.slice(2);
|
|
const scaffoldDir = args[0] || process.cwd();
|
|
const outputFile = args[1] || "codebase-extract.md";
|
|
|
|
console.log(`Extracting code from: ${scaffoldDir}`);
|
|
console.log(`Output will be written to: ${outputFile}`);
|
|
|
|
// Walk directory and get all files
|
|
const files = await walkDirectory(scaffoldDir, scaffoldDir);
|
|
console.log(`Found ${files.length} code files`);
|
|
|
|
// Format files
|
|
let output = `# Codebase Extract\nGenerated on: ${new Date().toISOString()}\nTotal files: ${
|
|
files.length
|
|
}\n\n`;
|
|
|
|
for (const file of files) {
|
|
output += formatFile(file, scaffoldDir);
|
|
}
|
|
|
|
// Write to output file
|
|
fs.writeFileSync(outputFile, output);
|
|
console.log(`Extraction complete. Output written to ${outputFile}`);
|
|
}
|
|
|
|
// Run the script
|
|
main().catch((error) => {
|
|
console.error("Error:", error);
|
|
process.exit(1);
|
|
});
|