generata
Version:
  
182 lines (149 loc) โข 5.52 kB
JavaScript
import fs from "fs";
import path from "path";
import chalk from "chalk";
import os from "os";
import { execSync } from "child_process";
import inquirer from "inquirer"; // โ added this line
// === CLI flags ===
const forceOverwrite = process.argv.includes("--force");
// === Helpers ===
const projectRoot = process.cwd();
const projectName = path.basename(projectRoot);
const packageJsonPath = path.join(projectRoot, "package.json");
const readmePath = path.join(projectRoot, "README.md");
// === Check if README already exists ===
if (fs.existsSync(readmePath) && !forceOverwrite) {
console.log(chalk.red("โ README.md already exists. Use --force to overwrite."));
process.exit(1);
}
// === Read Package.json ===
let dependencies = [], devDependencies = [], scripts = {};
let author = "Unknown", license = "UNLICENSED", description = "";
let repoUrl = "", nodeVersion = "", lastUpdated = "";
if (fs.existsSync(packageJsonPath)) {
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
dependencies = Object.keys(pkg.dependencies || {});
devDependencies = Object.keys(pkg.devDependencies || {});
scripts = pkg.scripts || {};
author = pkg.author || author;
license = pkg.license || license;
description = pkg.description || "";
repoUrl = typeof pkg.repository === "string"
? pkg.repository
: pkg.repository?.url || "";
}
// === Prompt for missing info ===
const promptForMissingInfo = async () => {
const questions = [];
if (!description) {
questions.push({
type: "input",
name: "description",
message: "No description found in package.json. Please provide one:",
});
}
if (!author || author === "Unknown") {
questions.push({
type: "input",
name: "author",
message: "No author found. Who is the author of this project?",
});
}
if (!license || license === "UNLICENSED") {
questions.push({
type: "input",
name: "license",
message: "No license found. Enter the license type (e.g., MIT):",
});
}
const answers = await inquirer.prompt(questions);
description = answers.description || description;
author = answers.author || author;
license = answers.license || license;
};
(async () => {
await promptForMissingInfo();
// === Get Node Version ===
try {
nodeVersion = process.version;
} catch (err) {
nodeVersion = "Unknown";
}
// === Last updated ===
lastUpdated = new Date().toISOString().split("T")[0];
// === Folder Structure ===
function getFolderTree(dir, depth = 0) {
const indent = " ".repeat(depth);
const items = fs.readdirSync(dir);
return items
.filter((item) => !item.startsWith(".") && item !== "node_modules")
.map((item) => {
const fullPath = path.join(dir, item);
if (fs.statSync(fullPath).isDirectory()) {
return `${indent}- ${item}/\n${getFolderTree(fullPath, depth + 1)}`;
} else {
return `${indent}- ${item}`;
}
})
.join("\n");
}
const folderStructure = getFolderTree(projectRoot);
// === Detect common config files ===
const configFiles = [".env", ".gitignore", ".eslintrc", ".prettierrc", "tsconfig.json"]
.filter(file => fs.existsSync(path.join(projectRoot, file)));
// === Detect frameworks ===
function detectFrameworks() {
const allDeps = [...dependencies, ...devDependencies].map(d => d.toLowerCase());
const known = [
{ name: "React", keyword: "react" },
{ name: "Next.js", keyword: "next" },
{ name: "Express", keyword: "express" },
{ name: "Tailwind CSS", keyword: "tailwind" },
{ name: "TypeScript", keyword: "typescript" },
{ name: "Redux", keyword: "redux" },
{ name: "Mongoose", keyword: "mongoose" },
];
return known.filter(({ keyword }) => allDeps.includes(keyword)).map(f => `- ${f.name}`);
}
const frameworks = detectFrameworks();
// === Scripts with explanations ===
const scriptDescriptions = {
dev: "Start the app in development mode",
build: "Build the app for production",
start: "Start the production server",
lint: "Lint the codebase",
test: "Run tests",
};
const scriptLines = Object.entries(scripts).map(
([key, val]) => `- \`${key}\`: ${val} ${scriptDescriptions[key] ? `โ ${scriptDescriptions[key]}` : ""}`
);
// === Template ===
const readme = `# ${projectName}



${description ? `> ${description}` : ""}
${repoUrl ? `๐ฆ Repo: ${repoUrl.replace(/^git\+/, "")}\n` : ""}
## ๐ง Frameworks / Tools Detected
${frameworks.length ? frameworks.join("\n") : "- None detected"}
## โ๏ธ Config Files
${configFiles.length ? configFiles.map(f => `- ${f}`).join("\n") : "- None"}
## ๐ฆ Dependencies
${dependencies.length ? dependencies.map(dep => `- ${dep}`).join("\n") : "- No dependencies"}
## ๐งช Dev Dependencies
${devDependencies.length ? devDependencies.map(dep => `- ${dep}`).join("\n") : "- No dev dependencies"}
## ๐ Folder Structure
\`\`\`
${folderStructure}
\`\`\`
## ๐ Scripts
${scriptLines.length ? scriptLines.join("\n") : "- No scripts"}
## ๐ค Author
- ${author}
## ๐ License
- ${license}
`;
fs.writeFileSync(readmePath, readme, "utf-8");
console.log(chalk.green("โ
README.md generated successfully!"));
})();