UNPKG

rjweb-server

Version:

Easy and Robust Way to create a Web Server with Many Easy-to-use Features in NodeJS

341 lines (340 loc) 12.9 kB
#! /usr/bin/env node "use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var import__ = require("."); var import_rjutils_collection = require("rjutils-collection"); var import_logger = require("./classes/logger"); var import_server = __toESM(require("./classes/server")); var import_child_process = require("child_process"); var import_https = __toESM(require("https")); var import_yargs = __toESM(require("yargs")); var import_posix = __toESM(require("path/posix")); var import_path = __toESM(require("path")); var import_fs = __toESM(require("fs")); const prefix = `\u26A1 ${import_logger.colors.fg.white}[RJWEB ${import__.Version.split(".")[0]}]${import_logger.colors.fg.gray}:${import_logger.colors.reset}`; const coloredPath = (path2) => { let output = []; for (const part of path2.split("/")) { output.push(`${import_logger.colors.fg.blue}${part}`); } return output.join(`${import_logger.colors.fg.cyan}/`); }; const pR = (location) => { return import_path.default.join(process.cwd(), location); }; const isX = (type, path2) => { let infos; try { infos = import_fs.default.statSync(path2); } catch { return false; } if (type === "dir") return infos.isDirectory(); else return infos.isFile(); }; import_yargs.default.scriptName("rjweb").usage("$0 <command> [args]").version(import__.Version).command( "serve <folder>", "Serve a Folder", (cmd) => cmd.positional("folder", { type: "string", description: "The Folder to serve", demandOption: true }).option("port", { type: "number", description: "The port on which to serve", alias: ["p"], default: 8080 }).option("hideHTML", { type: "boolean", description: "Whether to remove html file endings", alias: ["html", "h", "hH"], default: false }).option("compress", { type: "boolean", description: "Whether to compress outgoing data", alias: ["C"], default: true }).option("cors", { type: "boolean", description: "Whether to enable * CORS headers", alias: ["c"], default: false }).option("proxy", { type: "boolean", description: "Whether to enable using X-Forwarded-For Header", alias: ["P"], default: false }).option("bind", { type: "string", description: "Where to bind the Server to", alias: ["b"], default: "0.0.0.0" }).option("404-file", { type: "string", description: "The file to print when a route is not found", alias: ["404"], default: "" }).option("dashboard", { type: "boolean", description: "Whether to enable the built-in dashboard (/rjweb-dashboard)", alias: ["d", "dash"], default: false }).option("dashboard-password", { type: "string", description: "The password for the dashboard", alias: ["dP", "pass"], default: "" }), (args) => { if (!isX("dir", pR(args.folder ?? "//"))) return console.error(`${prefix} ${import_logger.colors.fg.red}Couldnt find ${import_logger.colors.fg.cyan}${args.folder}`); if (args["404File"] && !isX("file", pR(args["404File"] ?? "//"))) return console.error(`${prefix} ${import_logger.colors.fg.red}Couldnt find ${import_logger.colors.fg.cyan}${args["404File"]}`); const server = new import_server.default({ port: args.port, dashboard: { enabled: args.dashboard, password: args.dashboardPassword }, httpCompression: { enabled: args.compress }, cors: args.cors, proxy: { enabled: args.proxy }, bind: args.bind }, []); server.path( "/", (path2) => path2.static(pR(args.folder), { hideHTML: args.hideHTML }) ); server.on("httpRequest", (ctr) => { console.log(`${prefix} ${import_logger.colors.fg.gray}${ctr.client.ip} ${import_logger.colors.fg.green}HTTP ${ctr.url.method} ${import_logger.colors.fg.cyan}${coloredPath(ctr.url.path)}`); }); if (args["404File"]) server.on("route404", (ctr) => { ctr.status(import__.Status.NOT_FOUND).printFile(pR(args["404File"])); }); server.start().then((port) => { console.log(`${prefix} ${import_logger.colors.fg.green}Started on Port ${import_logger.colors.fg.cyan}${port}`); }).catch((err) => { console.error(`${prefix} ${import_logger.colors.fg.red}An Error occured while starting the Server:`); console.error(`${import_logger.colors.fg.cyan}${err.stack}`); process.exit(1); }); } ).command( "generate <folder>", "Generate a template Project", (cmd) => cmd.positional("folder", { type: "string", description: "The Folder to generate the template in", demandOption: true }).option("template", { type: "string", description: "Which template to use", alias: ["E"], default: "choose" }).option("variant", { type: "string", description: "The Variant of the template to use", alias: ["V"], default: "choose" }), async (args) => { const { default: inquirer } = await import("inquirer"); console.log(`${prefix} ${import_logger.colors.fg.gray}Fetching Templates from GitHub...`); const templates = []; JSON.parse((await new Promise((resolve, reject) => { const chunks = []; import_https.default.get({ path: "/repos/0x7d8/NPM_WEB-SERVER/contents/templates", host: "api.github.com", port: 443, headers: { "User-Agent": `rjweb-server@cli ${import__.Version}`, "Accept": "application/vnd.github.v3+json" } }, (res) => { res.on("data", (data) => { chunks.push(data); }).once("error", reject).once("end", () => { resolve(Buffer.concat(chunks)); }); }); })).toString()).filter((t) => t.type === "dir").forEach((template2) => { const variant2 = template2.name.match(/\[.*\] /)[0].replace(/\[|\]/g, "").trim(); const name = template2.name.replace(/\[.*\] /, ""); if (templates.some((t) => t.name === name)) { const index = templates.findIndex((t) => t.name === name); templates[index].variants.push({ name: variant2, git: template2 }); } else { templates.push({ name, variants: [ { name: variant2, git: template2 } ] }); } }); let template = "", variant = ""; if (args.template !== "choose" && templates.some((t) => t.name === args.template)) { template = args.template; console.log(`${prefix} ${import_logger.colors.fg.gray}Using ${import_logger.colors.fg.cyan}${template}`); } else { if (args.template !== "choose") console.log(`${prefix} ${import_logger.colors.fg.cyan}${args.template} ${import_logger.colors.fg.red}is not a valid template!`); await inquirer.prompt([ { name: "Template", type: "list", prefix, choices: templates.map((t) => t.name), askAnswered: true } ]).then((answers) => { template = answers.Template; }); } if (args.variant !== "choose" && templates.some((t) => t.name === args.variant)) { variant = args.variant; console.log(`${prefix} ${import_logger.colors.fg.gray}Using Variant ${import_logger.colors.fg.cyan}${variant}`); } else { if (args.variant !== "choose") console.log(`${prefix} ${import_logger.colors.fg.cyan}${args.template} ${import_logger.colors.fg.red}is not a valid template!`); await inquirer.prompt([ { name: "Variant", type: "list", prefix, choices: templates.find((t) => t.name === template).variants.map((v) => v.name), askAnswered: true } ]).then((answers) => { variant = answers.Variant; }); } if (!import_fs.default.existsSync(import_path.default.join(process.cwd(), args.folder))) { await import_fs.default.promises.mkdir(import_path.default.join(process.cwd(), args.folder)); } console.log(`${prefix} ${import_logger.colors.fg.gray}Generating Template Project...`); const handleDirectory = async (directory) => { const files = JSON.parse((await new Promise((resolve, reject) => { const chunks = []; import_https.default.get({ path: new URL(directory).pathname, host: "api.github.com", port: 443, headers: { "User-Agent": `rjweb-server@cli ${import__.Version}`, "Accept": "application/vnd.github.v3+json" } }, (res) => { res.on("data", (data) => { chunks.push(data); }).once("error", reject).once("end", () => { resolve(Buffer.concat(chunks)); }); }); })).toString()); if (Array.isArray(files)) { for (const file of files) { if (file.type === "dir") { if (!import_fs.default.existsSync(import_posix.default.join(process.cwd(), args.folder, file.path.replace(`templates/[${variant}] ${template}`, "")))) { await import_fs.default.promises.mkdir(import_posix.default.join(process.cwd(), args.folder, file.path.replace(`templates/[${variant}] ${template}`, ""))); } } await handleDirectory(file.url); } } else { const file = files; if (file.name === "yarn.lock") return; console.log(`${prefix} ${import_logger.colors.fg.green}Downloaded ${import_logger.colors.fg.cyan}${import_path.default.join(args.folder, file.path.replace(`templates/[${variant}] ${template}`, ""))}`); await import_fs.default.promises.writeFile(import_path.default.join(process.cwd(), args.folder, file.path.replace(`templates/[${variant}] ${template}`, "")), Buffer.from(file.content, "base64").toString()); } }; await handleDirectory(templates.find((t) => t.name === template).variants.find((v) => v.name === variant).git.url); console.log(""); console.log(`${prefix} ${import_logger.colors.fg.green}Template Project Generated!`); console.log(""); let availablePackageManagers = []; try { (0, import_child_process.execSync)("npm --version", { stdio: "ignore" }); availablePackageManagers.push("npm"); } catch { } try { (0, import_child_process.execSync)("yarn --version", { stdio: "ignore" }); availablePackageManagers.push("yarn"); } catch { } try { (0, import_child_process.execSync)("pnpm --version", { stdio: "ignore" }); availablePackageManagers.push("pnpm"); } catch { } let continueWith = "npm"; await inquirer.prompt([ { name: "Continue with", type: "list", prefix, choices: availablePackageManagers, askAnswered: true } ]).then((answers) => { continueWith = answers["Continue with"]; }); const spinner = new import_rjutils_collection.Spinner(); const runInterval = () => { process.stdout.write(`\r${prefix} ${import_logger.colors.fg.yellow}${spinner.get()} ${import_logger.colors.fg.gray}Installing Dependencies with ${import_logger.colors.fg.cyan}${continueWith}${import_logger.colors.fg.gray}...`); }; const interval = setInterval(runInterval, 175); runInterval(); process.chdir(import_path.default.join(process.cwd(), args.folder)); (0, import_child_process.exec)(`${continueWith} install`, () => { clearInterval(interval); process.stdout.write("\n"); console.log(`${prefix} ${import_logger.colors.fg.green}Installed Dependencies!${import_logger.colors.reset}`); }); } ).help().argv;