123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- #!/usr/bin/env node
- const yargs = require("yargs");
- const importFresh = require("import-fresh");
- const { colors, Errors } = require("svcorelib");
- const { resolve } = require("path");
- const dotenv = require("dotenv");
- const settings = require("../settings");
- const { exit } = process;
- const col = colors.fg;
- /** Absolute path to JokeAPI's root directory */
- const rootDir = resolve(__dirname, "../"); // if this file is moved, make sure to change this accordingly
- //#SECTION run
- async function run()
- {
- try
- {
- // ensure cwd is correct if the binary is called in a global context
- process.chdir(rootDir);
- dotenv.config();
- const argv = prepareCLI();
- /** @type {string|null} */
- const command = argv && argv._ ? argv._[0] : null;
- let file, action;
- // TODO: (v2.4) remove comments below
- switch(command)
- {
- case "start":
- case "run":
- file = "../JokeAPI.js";
- break;
- case "submissions":
- case "sub":
- case "s":
- action = "Joke submissions";
- file = "./submissions.js";
- break;
- case "info":
- case "i":
- file = "./info.js";
- break;
- case "add-joke":
- case "aj":
- case "j":
- action = "Add joke";
- file = "./add-joke.js";
- break;
- case "reassign-ids":
- case "ri":
- action = "Reassign IDs";
- file = "./reassign-ids.js";
- break;
- case "add-token":
- case "at":
- case "t":
- action = "Add API token";
- file = "./add-token.js";
- break;
- case "validate-ids":
- case "vi":
- action = "Validate IDs";
- file = "./validate-ids.js";
- break;
- case "validate-jokes":
- case "vj":
- action = "Validate jokes";
- file = "./validate-jokes.js";
- break;
- case "generate-changelog":
- case "cl":
- action = "Generate changelog";
- file = "./generate-changelog.js";
- break;
- // case "stresstest": case "str":
- // action = "Stress test";
- // file = "./stresstest.js";
- // break;
- case "test":
- action = "Unit tests";
- file = "./test.js";
- break;
- // case "ip-info": case "ip":
- // action = "IP info";
- // file = "./ip-info.js";
- case undefined:
- case null:
- case "":
- console.log(`${settings.info.name} CLI v${settings.info.version}\n`);
- return yargs.showHelp();
- default:
- return warn(`Unrecognized command '${command}'\nUse '${argv.$0} -h' to see a list of commands`);
- }
- if(!file)
- throw new Error(`Command '${command}' (${action.toLowerCase()}) didn't yield an executable file`);
- action && console.log(`${settings.info.name} CLI - ${action}`);
- return importFresh(file);
- }
- catch(err)
- {
- return error(err);
- }
- }
- /**
- * Prepares the CLI so it can show help
- * @returns {yargs.Argv<*>}
- */
- function prepareCLI()
- {
- //#SECTION general
- yargs.scriptName("jokeapi")
- .usage("Usage: $0 <command>")
- .version(`${settings.info.name} v${settings.info.version} - ${settings.info.projGitHub}`)
- .alias("v", "version")
- .help()
- .alias("h", "help");
- //#SECTION commands
- // TODO: (v2.4) remove comments below
- yargs.command([ "start", "run" ], `Starts ${settings.info.name} (equivalent to 'npm start')`);
- yargs.command([ "info", "i" ], `Prints information about ${settings.info.name}, like the /info endpoint`);
- yargs.command([ "submissions", "sub", "s" ], "Goes through all joke submissions, prompting to edit, add or delete them");
- yargs.command([ "add-joke", "aj", "j" ], "Runs an interactive prompt that adds a joke");
- yargs.command([ "reassign-ids", "ri", "r" ], "Goes through each joke file and reassigns IDs to each one, consecutively");
- yargs.command([ "add-token [amount]", "at", "t" ], "Generates one or multiple API tokens to be used to gain unlimited access to the API", cmd => {
- cmd.positional("amount", {
- describe: "Specifies the amount of tokens to generate - min is 1, max is 10",
- type: "number",
- default: 1
- });
- // cmd.option("no-copy", {
- // alias: "nc",
- // describe: "Disables auto-copying the token to the clipboard (if amount = 1)",
- // type: "boolean"
- // });
- });
- yargs.command([ "validate-ids", "vi" ], "Goes through each joke file and makes sure the IDs are correct (no duplicates or skipped IDs & correct order)");
- yargs.command([ "validate-jokes", "vj" ], "Goes through each joke file and checks the validity of each joke and whether they can all be loaded to memory");
- yargs.command([ "generate-changelog", "cl" ], "Turns the changelog.txt file into a markdown file (changelog.md)", cmd => {
- cmd.option("generate-json", {
- alias: "j",
- describe: "Use this argument to generate a changelog-data.json file in addition to the markdown file",
- type: "boolean"
- });
- });
- // yargs.command([ "ip-info", "ip" ], "Starts a server at '127.0.0.1:8074' that just prints information about each request's IP", cmd => {
- // cmd.option("color-cycle", {
- // alias: "c",
- // describe: "Cycles the color of the output after each request (to make spotting a new request easier)",
- // type: "boolean"
- // });
- // });
- // yargs.command([ "stresstest", "str" ], `Sends lots of requests to ${settings.info.name} to stresstest it (requires the API to run in another process on the same machine)`);
- yargs.command("test", `Runs ${settings.info.name}'s unit tests`, cmd => {
- cmd.option("colorblind", {
- alias: "c",
- describe: "Include this argument to replace the colors green with cyan and red with magenta",
- type: "boolean"
- });
- });
- yargs.wrap(Math.min(100, process.stdout.columns));
- return yargs.argv;
- }
- //#SECTION on execute
- try
- {
- if(!process.stdin.isTTY)
- throw new Errors.NoStdinError("The process doesn't have an stdin channel to read input from");
- else
- run();
- }
- catch(err)
- {
- return error(err);
- }
- /**
- * @param {Error} err
- */
- function error(err)
- {
- console.error(`${col.red}${settings.info.name} CLI - ${err.name}:${col.rst}\n${err.stack}\n`);
- exit(1);
- }
- /**
- * @param {string} warning
- * @param {string} [type]
- */
- function warn(warning, type = "Warning")
- {
- console.log(`${col.yellow}${settings.info.name} CLI - ${type}:${col.rst}\n${warning}\n`);
- exit(1);
- }
|