- Introduction
- Installation
- Basic example: wrapping an existing library
- Command line integration
- Interactive CLI
- Script mode
- Constants
- [Macros and variables](#macros-and-variables
JARVIS helps you write rudimentary English wrappers around libraries or APIs, like this:
// wrap your JavaScript function with an English API:
jarvis.addCommand({
command: '$number to the power of $power',
handler: ({args: {number, power}}) => {
const result = Math.pow(parseInt(number), parseInt(power));
return `${number} to the power of ${power} is ${result}!`;
}
});
Use it from an interactive command line prompt
> 2 to the power of 3
2 to the power of 3 is 8!
npm install --save hliyan/jarvis
Invoke an API using natural language.
const Jarvis = require('jarvis'); // use jarvis to
const IssueClient = require('issue-client'); // wrap this with a basic english API
const app = new Jarvis();
const client = new IssueClient();
// register command
app.addCommand({
command: 'connectToRepository $repoName',
aliases: [
'connect to $repoName',
'connect repo $repoName',
'connect to $repoName repo'
],
handler: async ({args: {repoName}}) => {
const res = await client.connect(repoName);
return res.success ? `Connected to ${repoName}.` : `Could not connect to ${repoName}. Here's the error: ${res.error}`;
}
});
// exercise the command
const res = await app.send('connect to hliyan/jarvis');
console.log(res); // "Connected to hliyan/jarvis."
Invoke an API using natural language, as a shell command.
const FAQClient = require('./faq'); // business logic from here
const Jarvis = require('jarvis'); // wrapped by jarvis
const readline = require('readline'); // and connected to a command line
const app = new Jarvis();
const client = new FAQClient();
// register the command
app.addCommand({
command: 'getCountryPresident $country',
aliases: [
'who is the president of $country',
'$country president'
],
handler: async ({args: {country}}) => {
const president = await client.getPresident(country);
return president ? `the president of ${country} is ${president}`
: `i don't know ${country}`;
}
});
// start the CLI
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'jarvis> '
});
rl.prompt();
// feed CLI input to the app, and app output back to CLI
rl.on('line', async (line) => {
const res = await app.send(line.trim());
console.log(res ? ` ${res}` : ' I don\'t understand');
rl.prompt();
});
// TODO: error handling and other best practices
Running:
$ node index.js
jarvis> who is the president of russia
the president of russia is Vladamir Putin
jarvis> usa president
the president of usa is Barack Obama
jarvis> us president
i don't know us
jarvis> foo
I don't understand
jarvis>
- Full source: hliyan/jarvis-sample-app
Use this when the workflow you're trying to wrap is too complicated to execute as a single line command.
You can enter an interactive command session using jarvis.startCommand($name)
and exit that particular session using jarvis.endCommand()
. State that needs to be maintained for the duration of the interactive session can be set using jarvis.setCommandState($object)
.
const jarvis = new Jarvis();
jarvis.addCommand({
command: 'repl',
handler: ({context, line}) => {
if (!context.activeCommand) {
context.startCommand('repl');
context.setCommandState({status: 'awaitInput'});
return 'Enter input: ';
}
if (context.state.status === 'awaitInput') {
const out = 'Handled: ' + line;
return out;
}
}
});
Expected output
$ repl
$ Enter input:
$ bar
$ Handled: bar
$ .. # built in exit
$ Done with repl.
You can use this to run your natural language commands as a script.
Create a script file, e.g.
start
connect to repo 'hliyan/jarvis'
get open issues
write issues to 'home/john/issues.json'
end
Create a script runner with the correct bindings
const Jarvis = require('jarvis');
const app = new Jarvis();
// bind commands as described earlier
// run script
app.run('test.jarvis', function(input, output) {
console.log(input);
console.log(output);
});
in this context
HOME is 'https://foo.bar.com'
USER is 'john'
end
You can use this to re-use blocks of commands within a script.
in this context
PI is 3.14
end
how to get area of circle with radius $radius
# more statements here
end