scaffdir
Version:
Generate folders and files from a simple tree
103 lines (102 loc) โข 3.77 kB
JavaScript
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."));
}