UNPKG

project-structure-cli

Version:

It is a lightweight app to create project structure so that it can be used optimally with LLMs or in creating README

97 lines (80 loc) 3.47 kB
#!/usr/bin/env node const fs = require("fs"); const path = require("path"); const OUTPUT_FILE = "project-structure.txt"; /** * Generates the directory structure as a formatted tree. * @param {string} dir - Directory path to scan. * @param {string} prefix - Prefix for indentation. * @param {Set<string>} ignorePaths - Paths to ignore. * @param {Set<string>} includePaths - Paths to explicitly include. * @returns {string} - Directory structure. */ function generateStructure(dir, prefix = "", ignorePaths = new Set(), includePaths = new Set()) { let structure = ""; const files = fs.readdirSync(dir) .filter(file => { const fullPath = path.join(dir, file); const isHidden = file.startsWith("."); // Check if it's a dotfile return ( (!ignorePaths.has(file) || includePaths.has(file)) && // Ignore only if not explicitly included (!isHidden || includePaths.has(file)) // Allow hidden files if explicitly included ); }); files.forEach((file, index) => { const fullPath = path.join(dir, file); const isLast = index === files.length - 1; const newPrefix = prefix + (isLast ? " " : "| "); structure += `${prefix}${isLast ? "└── " : "├── "}${file}\n`; if (fs.statSync(fullPath).isDirectory()) { structure += generateStructure(fullPath, newPrefix, ignorePaths, includePaths); } }); return structure; } /** * Parses command-line arguments for --include and --ignore. * @returns {Object} - Contains ignorePaths and includePaths. */ function parseArgs() { const args = process.argv.slice(2); const ignorePaths = new Set([ "node_modules" ,".git"]); // Default ignored paths const includePaths = new Set(); let includeIndex = args.indexOf("--include"); let ignoreIndex = args.indexOf("--exclude"); if (includeIndex !== -1) { args.slice(includeIndex + 1).forEach(item => { if (!item.startsWith("--")) { includePaths.add(item); ignorePaths.delete(item); // Ensure included items are not ignored } }); } if (ignoreIndex !== -1) { args.slice(ignoreIndex + 1).forEach(item => { if (!item.startsWith("--") && !includePaths.has(item)) { ignorePaths.add(item); // Add to ignore list only if not included } }); } // If no `--exclude` or `--include` is present but arguments exist, treat them as excluded paths if (includeIndex === -1 && ignoreIndex === -1 && args.length > 0) { args.forEach(item => ignorePaths.add(item)); } return { ignorePaths, includePaths }; } /** * Writes the project structure to a file. * @param {Set<string>} ignorePaths - Set of paths to ignore. * @param {Set<string>} includePaths - Set of paths to explicitly include. */ function saveStructureToFile(ignorePaths, includePaths) { const projectRoot = process.cwd(); const structure = `${path.basename(projectRoot)}\n${generateStructure(projectRoot, "", ignorePaths, includePaths)}`; fs.writeFileSync(path.join(projectRoot, OUTPUT_FILE), structure, "utf8"); console.log(`✅ Project structure saved to ${OUTPUT_FILE}`); } // Parse CLI arguments const { ignorePaths, includePaths } = parseArgs(); // Run the function when the script is executed saveStructureToFile(ignorePaths, includePaths);