UNPKG

scaffdir

Version:

Generate folders and files from a simple tree

103 lines (102 loc) โ€ข 3.77 kB
#!/usr/bin/env node import { Command } from "commander"; import { readFileSync } from "fs"; import { mkdir, writeFile } from "fs/promises"; import path from "path"; import chalk from "chalk"; const program = new Command(); program .name("scaffdir") .description("๐Ÿ“ Generate folders and files from a text-based file tree") .version("0.1.0") .option("-f --file <file>", "๐Ÿ“„ Read structure from a text file") .option("-o --output <dir>", "๐Ÿ“‚ Output directory (default: current directory)") .option("-d, --dry-run", "๐Ÿงช Simulate creation without writing to disk"); program.parse(); const options = program.opts(); const isDryRun = options.dryRun; if (options.file) { console.log(chalk.cyan(`๐Ÿ“˜ Reading structure from: ${chalk.bold(options.file)}`)); const outputDir = options.output ? options.output : process.cwd(); console.log(chalk.cyan(`๐Ÿ“‚ Output directory: ${chalk.bold(outputDir)}`)); let fileContent; try { fileContent = readFileSync(options.file, "utf-8"); } catch (error) { console.error(chalk.bgRed.white("โŒ Error reading file:"), error); process.exit(1); } const lines = fileContent.split("\n"); let indentSize = 2; for (const line of lines) { const trimmedLine = line.trim(); if (trimmedLine !== "") { const leadingSpaces = line.search(/\S/); if (leadingSpaces > 0) { indentSize = leadingSpaces; break; } } } const tree = []; const currentPath = []; lines.forEach((line) => { const trimmedLine = line.trim(); if (trimmedLine === "") return; const indent = line.search(/\S/); const depth = Math.floor(indent / indentSize); const isFolder = trimmedLine.endsWith("/"); const item = { name: trimmedLine.replace("/", ""), type: isFolder ? "folder" : "file", children: [], }; if (depth === 0) { tree.push(item); currentPath[0] = item; } else { const parent = currentPath[depth - 1]; parent.children.push(item); currentPath[depth] = item; } }); async function createStructure(tree, basePath) { for (const item of tree) { const itemPath = path.join(basePath, item.name); if (item.type === "folder") { if (isDryRun) { console.log(chalk.gray(`๐Ÿ—‚๏ธ Would create folder: ${itemPath}`)); } else { await mkdir(itemPath, { recursive: true }); console.log(chalk.green(`๐Ÿ“ Created folder: ${itemPath}`)); } if (item.children) { await createStructure(item.children, itemPath); } } else { if (isDryRun) { console.log(chalk.yellow("๐Ÿšซ Dry run mode โ€” no files or folders will be created.")); console.log(chalk.gray(`๐Ÿ“„ Would create file: ${itemPath}`)); } else { await writeFile(itemPath, ""); console.log(chalk.green(`๐Ÿ“ Created file: ${itemPath}`)); } } } } (async () => { await createStructure(tree, outputDir); console.log(chalk.bgGreen.black("โœ… Done!"), isDryRun ? chalk.gray(" (Dry run: no changes were made.)") : chalk.white(" File structure successfully created.")); })(); } else { console.log(chalk.red("โš ๏ธ Please provide a file with the -f option to specify your structure.")); }