Bring your cli to the next level by pushing your terminal prompts to the web.
If you like it, I would be super-happy if you star me on github :)
- You want to create a wizard doing things for you.
- You want to keep track of stuff on your node sripts running locally
- You want to use your CLI remotely
- You want to collaborate on your CLI with multiple co-workers
- You want to continue using your CLI tomorrow. Simply close and reopen it.
- You want to have some super complex user interface which your current CLI ist simply not capable of
- You want to prompt multiple things at the same time and you dont care the order the user responds to it. (have fun with some async-await-promise-magic)
cli-to-web creates an interface between your node-cli and you over websockets. It can ask you things like "please enter a password i need to continue processing", notify and update you how far the process is like "i am 95% done", send error- and normal messages like "I'm done compressing all your moviefiles".
simple as it should be:
npm install cli-to-web
Instantiate it on every node.js-file you need it. It is a singleton and you dont need to pass the instance of cli-to-web
const {ui, Question, Answer, Template} = require("cli-to-web");
ui.tell("Hello web interface");
Open the browser
You dont need to open the browser this way. You can also open it manually at any point in time. You can close your browser and reopen it later. All submitted progress is stored.
ui.show();
Close Webserver
ui.finish();
Show a simple message
ui.tell("Hey, you rock!");
Warning message
ui.warn("something is weird but still running.");
Error message
const errormessage = ...
ui.error("something failed. here is your stacktrace: " + errormessage);
Ask a html-page. For more complex pages including js and css, please see Templates
const answer = await ui.ask("Enter some value please: <input id='idOnHTML-page'>");
const someValue = answer.getValue("idOnHTML-page");
Ask with predefined templates
const question = new Question();
question.addString("projectName", "Whats the name of your product?", 20);
question.addNumber("someNumber", "please enter some number", 3);
question.addChoice("someChoice", "please choose", ["answer1", "answer2", "answer3"]);
question.addMultipleChoice("multipleChoice", "please choose multiple", ["answer1", "answer2", "answer3"]);
question.addColor("someColor", "Tell me a color");
question.addDate("someDate", "Tell me a date");
question.addTime("someTime", "Whats your current time?");
question.addRange("someValue", "I like rangesliders", 1, 100);
question.addCheckbox("someBool", "please check", false);
const answer = await ui.ask(question);
// read result
const projectName = answer.getValue("projectName");
Show and update progress
const progressId = ui.showProgress("Doing some calculations ... please wait");
// do something time intensive
ui.updateProgress(progressId, 25);
// do something time intensive
ui.updateProgress(progressId, 50);
// do something time intensive
ui.updateProgress(progressId, 75);
// do something time intensive
ui.updateProgress(progressId, 100, "Im done!");
Show no progress, just keep and update the text
const progressId = ui.showProgress();
ui.updateProgress(progressId, ui.PROGRESS_INVISIBLE, "Doing something");
ui.updateProgress(progressId, ui.PROGRESS_INVISIBLE, "... and now something else");
ui.updateProgress(progressId, ui.PROGRESS_INVISIBLE, "... surprise!");
Show indetermined progress (moving stripes, filled progressbar)
const progressId = ui.showProgress();
ui.updateProgress(progressId, ui.PROGRESS_INDETERMINED, "dont know how long this might take");
Create your 100% custom Prompts and Editors using templates. For more information about templating, please find the attached example 5.js
const templateId = "myForm";
const templatePath = __dirname + "/myTemplate";
const myCustomQuestion = ui.registerTemplate(templateId, templatePath);
async function askTemplate() {
const answer = await ui.ask(myCustomQuestion);
console.log("Your values:");
console.log(answer.getValue("valuesFromIframe1"));
console.log(answer.getValue("valuesFromIframe2"));
console.log(answer.getValue("valuesFromIframe3"));
}
Sending data to template works by passing an object to ui.ask:
const myData = {somethingINeed: "foo", moreInformation: "bar"};
const answer = await ui.ask(myCustomQuestion, myData);
You will also need a function in your template to receive the data.
// api will be injected as soon as "apiLoaded" was triggered
window.addEventListener("apiLoaded", ready);
function ready() {
// receive parameters from node
const parameters = api.getNodeParams();
console.log(parameters.somethingINeed);
console.log(parameters.moreInformation);
// rescale your iframe (will be done initially)
api.rescale();
// get iframe instance.. just in case you need it
const iframe = api.getIframe();
}
You can also specify a URL for your template to call your external helper-tools.
Simply use an URL for the templatePath.
But take care: You need to take care for the cross-origin problem yourself. Maybe with a crossdomain.xml file
const templateId = "myForm";
const templatePath = "0.0.0.0:80/myCoolForm";
const myCustomQuestion = ui.registerTemplate(templateId, templatePath);
defaultport is 3000, but can be changed to anything you like.
Bash:
PORT=3001 node ./myNodeApp.js
Windows Powershell:
$env:PORT=3001
node ./myNodeApp.js
Windows CMD:
SET PORT=3001
node ./myNodeApp.js
Please discover the examples under examples/
Run them:
node ./node_modules/cli-to-web/examples/1.js // simple messages
node ./node_modules/cli-to-web/examples/2.js // show progress
node ./node_modules/cli-to-web/examples/3.js // asking html-content
node ./node_modules/cli-to-web/examples/4.js // asking predefined questions
node ./node_modules/cli-to-web/examples/5.js // using templates
node ./node_modules/cli-to-web/examples/6.js // replace your remote-ssh-commands with buttons
node ./node_modules/cli-to-web/examples/7.js // example-wizard