UNPKG

@cvyadnik/quicknode

Version:

A CLI tool to quickly generate Node.js + Express projects with database setup

297 lines (259 loc) • 8.02 kB
#!/usr/bin/env node import fs from "fs-extra"; import path from "path"; import inquirer from "inquirer"; import chalk from "chalk"; import { execSync } from "child_process"; import figlet from "figlet"; import shell from "shelljs"; // Display QuickNode CLI title console.log( chalk.blue(figlet.textSync("QuickNode", { horizontalLayout: "full" })) ); console.log(chalk.green("\nšŸš€ Welcome to QuickNode - by Chetan Yadnik\n")); // Database options const databases = { mongoose: { name: "MongoDB (Mongoose)", package: "mongoose", dbFile: ` const mongoose = require("mongoose"); require("dotenv").config(); const connectDB = async () => { try { await mongoose.connect(process.env.DB_URI, { useNewUrlParser: true, useUnifiedTopology: true }); console.log("āœ… MongoDB Connected!"); } catch (error) { console.error("āŒ MongoDB Connection Error:", error); process.exit(1); } }; module.exports = connectDB; `, }, "mysql2 sequelize": { name: "MySQL (Sequelize)", package: "mysql2 sequelize", dbFile: ` const { Sequelize } = require("sequelize"); require("dotenv").config(); const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, { host: process.env.DB_HOST, dialect: "mysql", logging: false }); module.exports = sequelize; `, }, "pg pg-hstore sequelize": { name: "PostgreSQL (Sequelize)", package: "pg pg-hstore sequelize", dbFile: ` const { Sequelize } = require("sequelize"); require("dotenv").config(); const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, { host: process.env.DB_HOST, dialect: "postgres", logging: false }); module.exports = sequelize; `, }, "sqlite3 sequelize": { name: "SQLite (Sequelize)", package: "sqlite3 sequelize", dbFile: ` const { Sequelize } = require("sequelize"); require("dotenv").config(); const sequelize = new Sequelize({ dialect: "sqlite", storage: "./database.sqlite", logging: false }); module.exports = sequelize; `, }, }; // Prompt user for project details inquirer .prompt([ { type: "input", name: "projectName", message: "šŸ“Œ Enter your project name:", validate: (input) => (input ? true : "Project name cannot be empty!"), }, { type: "list", name: "database", message: "šŸ›¢ Select a database:", choices: Object.values(databases).map((db) => ({ name: db.name, value: db.package, })), }, ]) .then(({ projectName, database }) => { const projectPath = path.join(process.cwd(), projectName); if (fs.existsSync(projectPath)) { console.log(chalk.red("āŒ Project already exists! Choose another name.")); process.exit(1); } console.log(chalk.yellow("\nšŸ”§ Setting up project structure...\n")); // Folder Structure const folders = [ "src", "src/config", "src/controllers", "src/models", "src/routes", "src/services", "src/middlewares", "src/utils", "src/validations", "src/logs", "tests", ]; shell.mkdir( "-p", folders.map((folder) => path.join(projectPath, folder)) ); // Create package.json const packageJson = { name: projectName, version: "1.0.0", main: "src/server.js", scripts: { start: "node src/server.js", dev: "nodemon src/server.js", }, dependencies: { express: "^4.18.2", dotenv: "^16.3.1", cors: "^2.8.5", helmet: "^7.1.1", jsonwebtoken: "^9.0.0", bcryptjs: "^2.4.3", joi: "^17.8.4", nodemon: "^2.0.15", }, }; const dbPackages = database.split(" "); // Split the database string into an array dbPackages.forEach((pkg) => (packageJson.dependencies[pkg] = "*")); fs.writeFileSync( path.join(projectPath, "package.json"), JSON.stringify(packageJson, null, 2) ); // Create .env file const envFile = ` # Environment Variables - Created by QuickNode by Chetan Yadnik PORT=5000 DB_URI=mongodb://localhost:27017/${projectName} DB_HOST=localhost DB_USER=root DB_PASS= DB_NAME=${projectName}_db `; fs.writeFileSync(path.join(projectPath, ".env"), envFile.trim()); // āœ… Create db.js based on selected database fs.writeFileSync( path.join(projectPath, "src/config/db.js"), databases[database].dbFile.trim() ); // āœ… Create app.js inside src/ fs.writeFileSync( path.join(projectPath, "src/app.js"), ` /** * Express App Setup - by Chetan Yadnik */ const express = require("express"); const cors = require("cors"); const helmet = require("helmet"); const userRoutes = require("./routes/userRoutes"); const errorHandler = require("./middlewares/errorHandler"); const app = express(); app.use(express.json()); app.use(cors()); app.use(helmet()); app.use("/api", userRoutes); app.use(errorHandler); module.exports = app; `.trim() ); // āœ… Ensure `userRoutes.js` is created inside `src/routes/` fs.mkdirSync(path.join(projectPath, "src/routes"), { recursive: true }); fs.writeFileSync( path.join(projectPath, "src/routes/userRoutes.js"), ` const express = require("express"); const { getUsers } = require("../controllers/userController"); const router = express.Router(); router.get("/", getUsers); module.exports = router; `.trim() ); // āœ… Ensure correct path in server.js fs.writeFileSync( path.join(projectPath, "src/server.js"), ` /** * Express Server - by Chetan Yadnik */ const express = require("express"); require("dotenv").config(); const path = require("path"); const app = require(path.join(__dirname, "./app")); // āœ… Fixed path const sequelize = require("./config/db"); const PORT = process.env.PORT || 5000; sequelize.sync().then(() => { console.log("āœ… Database synced successfully."); app.listen(PORT, () => console.log(\`šŸš€ Server running on http://localhost:\${PORT}\`)); }).catch(error => { console.error("āŒ Database connection failed:", error); }); `.trim() ); // āœ… Create errorHandler.js fs.writeFileSync( path.join(projectPath, "src/middlewares/errorHandler.js"), ` /** * Global Error Handler - by Chetan Yadnik */ const errorHandler = (err, req, res, next) => { console.error("āŒ Error:", err.stack); res.status(err.status || 500).json({ success: false, message: err.message || "Internal Server Error", }); }; module.exports = errorHandler; `.trim() ); // āœ… Ensure `userController.js` is created inside `src/controllers/` fs.mkdirSync(path.join(projectPath, "src/controllers"), { recursive: true, }); fs.writeFileSync( path.join(projectPath, "src/controllers/userController.js"), ` exports.getUsers = (req, res) => { res.json({ message: "Welcome to QuickNode API!", author: "Chetan Yadnik" }); }; `.trim() ); console.log(chalk.blue("\nšŸ“¦ Installing dependencies...\n")); try { execSync(`npm install`, { cwd: projectPath, stdio: "inherit" }); console.log(chalk.green("\nāœ… Dependencies installed successfully!")); } catch (error) { console.error(chalk.red("āŒ Error installing dependencies:"), error); } console.log(chalk.green("\nšŸŽ‰ Setup Complete!")); console.log(chalk.yellow(`šŸ‘‰ cd ${projectName} && npm run dev`)); console.log( chalk.yellow("šŸš€ Start building your API with QuickNode - by Chetan Yadnik!") ); }) .catch((error) => console.error(chalk.red("āŒ Error:", error)));