UNPKG

4bnode

Version:

4bnode is a CLI-powered backend development platform with a built-in visual dashboard to generate, manage, and test Node.js/Express APIs faster.

175 lines (146 loc) 7.3 kB
import fs from "fs"; import path from "path"; import chalk from "chalk"; import gradient from "gradient-string"; import ora from "ora"; import { addDepsToPackageJson } from "./codegen.js"; // Brand gradients const brand = gradient(["#00c6ff", "#0072ff", "#7b2ff7"]); const warm = gradient(["#f7971e", "#ffd200"]); const cool = gradient(["#00f260", "#0575e6"]); const fire = gradient(["#ff416c", "#ff4b2b"]); // Colors const dim = chalk.gray; const accent = chalk.hex("#00c6ff"); const highlight = chalk.hex("#ffd200").bold; const success = chalk.hex("#00f260").bold; const warn = chalk.hex("#ffd200"); const err = chalk.hex("#ff416c").bold; const info = chalk.hex("#0575e6"); const muted = chalk.hex("#888888"); const white = chalk.white; const bold = chalk.white.bold; const line = dim(" ─────────────────────────────────────────────────────"); const banner = ` ██╗ ██╗██████╗ ███╗ ██╗ ██████╗ ██████╗ ███████╗ ██║ ██║██╔══██╗████╗ ██║██╔═══██╗██╔══██╗██╔════╝ ███████║██████╔╝██╔██╗ ██║██║ ██║██║ ██║█████╗ ╚════██║██╔══██╗██║╚██╗██║██║ ██║██║ ██║██╔══╝ ██║██████╔╝██║ ╚████║╚██████╔╝██████╔╝███████╗ ╚═╝╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚══════╝`; // ── Banner ────────────────────────────────────────── export function showBanner() { console.log(brand(banner)); console.log(line); console.log( dim(" ") + bold("4Brains Technologies") + dim(" | Node.js Project Generator") ); console.log(line + "\n"); } // ── Section Header ────────────────────────────────── export function showHeader(command, description) { console.log(); console.log(dim(" ┌─────────────────────────────────────────────────┐")); console.log( dim(" │ ") + accent("◆ ") + highlight(command) + dim(" ") + white(description) + dim(" │") ); console.log(dim(" └─────────────────────────────────────────────────┘")); console.log(); } // ── Spinners ──────────────────────────────────────── export function createSpinner(text) { return ora({ text: muted(text), spinner: "dots12", color: "cyan", indent: 2, }); } // ── Step indicators ───────────────────────────────── export function showStep(step, total, text) { const progress = accent(`[${step}/${total}]`); console.log(` ${progress} ${white(text)}`); } // ── Success ───────────────────────────────────────── export function showSuccess(lines) { console.log(); console.log(dim(" ┌─────────────────────────────────────────────────┐")); console.log(dim(" │") + success(" ✔ Done!") + dim(new Array(42).join(" ") + "│")); console.log(dim(" └─────────────────────────────────────────────────┘")); console.log(); for (const l of lines) { console.log(dim(" │ ") + white(l)); } console.log(); } // ── Task complete (for add-* commands) ────────────── export function showTaskDone(title, details = []) { console.log(); console.log(` ${success("✔")} ${cool(title)}`); for (const d of details) { console.log(` ${dim("→")} ${muted(d)}`); } console.log(); } // ── Warning ───────────────────────────────────────── export function showWarning(message) { console.log(`\n ${warn("⚠")} ${warn(message)}\n`); } // ── Error ─────────────────────────────────────────── export function showError(message) { console.log(`\n ${err("✖")} ${err(message)}\n`); } // ── Info ──────────────────────────────────────────── export function showInfo(message) { console.log(` ${info("ℹ")} ${muted(message)}`); } // ── Next Steps ────────────────────────────────────── export function showNextSteps(steps) { console.log(accent.bold(" Next steps:\n")); for (let i = 0; i < steps.length; i++) { const num = highlight(` ${i + 1} `); console.log(` ${num} ${white(steps[i])}`); } console.log(); console.log(line); console.log(dim(" Happy coding! ") + brand("★ 4Brains")); console.log(line + "\n"); } // ── Installing deps (with spinner) ────────────────── export async function installDeps(packages, opts = {}) { const { execSync } = await import("child_process"); const { dev = false, ...execOpts } = opts; const names = Array.isArray(packages) ? packages : [packages]; const label = names.join(", "); // Record in package.json first, so the app is installable even if the live // install fails (offline) — a later `npm install` then resolves everything. try { const pkgPath = path.join(execOpts.cwd || process.cwd(), "package.json"); if (fs.existsSync(pkgPath)) { const { content, changed } = addDepsToPackageJson(fs.readFileSync(pkgPath, "utf8"), names, { dev }); if (changed) fs.writeFileSync(pkgPath, content, "utf8"); } } catch {} const spinner = createSpinner(`Installing ${label}...`); spinner.start(); try { execSync(`npm install ${dev ? "-D " : ""}${names.join(" ")}`, { stdio: "pipe", ...execOpts, }); spinner.succeed(success(`Installed ${label}`)); } catch (e) { spinner.fail(err(`Failed to install ${label}`)); throw e; } } // ── File action log ───────────────────────────────── export function showFileAction(action, filePath) { const icons = { created: chalk.hex("#00f260")("+ "), updated: chalk.hex("#0575e6")("~ "), deleted: chalk.hex("#ff416c")("- "), }; const icon = icons[action] || dim(" "); console.log(` ${icon}${muted(filePath)}`); }