A meteor package and command line tools for creating and running command line / cli programs with meteor.
To be able to reuse the same code of your meteor app in your command line programs, instead of having to create a separate node / npm code base with lot's of code duplicated from your meteor app.
# jq is a command-line JSON processor that the mcli command line tool depends on.
# Replace the first line with your linux's distribution way of installing packages.
sudo apt-get install -y jq
curl https://raw.githubusercontent.com/practicalmeteor/meteor-mcli/master/bin/install-starter-kit.sh | bash
cd starter-mcli-app
# Run the hello-world command in the meteor command line program.
mcli hello-world
The starter-mcli-app is a fully functional meteor command line program that you should use as a base.
You can include multiple commands in a single meteor command line program. To register your commands:
// defaultOptions and async are optional
CLI.registerCommand(commandName, functionToExecute, defaultOptions = {}, async = false);
For example:
var defaultOptions = { stderr: false };
var helloWorld = function(options) {
if(options.stderr)
console.error("Hello world from practicalmeteor:mcli!");
else
console.info("Hello world from practicalmeteor:mcli!");
};
CLI.registerCommand('hello-world', helloWorld, defaultOptions);
To run your command, just:
# Run this from your meteor command line program folder.
mcli hello-world --stderr=true
Or, with a meteor settings file:
mcli --settings my-settings.json hello-world --stderr=true
Unlike a meteor webapp, which never exits and therefore your async callbacks will always execute, command line programs with async callbacks will exit, unless you tell them not to using futures or mcli's simplified async API based on futures.
Here is an example async ls command from the starter-mcli-app:
var child_process = Npm.require('child_process');
// When you register your command as an async one,
// you need to call CLI.done() when your command has completed.
var lsCommand = function(options) {
var ls = child_process.spawn("ls");
ls.stdout.setEncoding("utf8");
ls.stdout.on("data", function(data){
process.stdout.write(data);
});
ls.stderr.setEncoding("utf8");
ls.stderr.on("data", function(data){
process.stderr.write(data);
});
// You need to wait on a child process's close event, and not on it's exit event,
// to make sure it has exited and all it's output has been delivered to you.
ls.on("close", function(code, signal){
// Calling CLI.done() will let CLI know your command has completed and it can exit.
CLI.done();
});
};
// When registering an async command, pass in true as the last argument.
CLI.registerCommand('ls', lsCommand, {}, true);
You have additional examples of commands, including commands that take command line arguments as well as options, in the starter-mcli-app command line program.
practicalmeteor:mcli uses the excellent rc npm command line parser and configurator.
When you register your command, you provide a json object with default values only for command line options you want default values for. When your command is called, it will get an options json object that will include all the options specified on the command line, as well as defaults you specified for options that were not included.
Command line options can also be specified using environment variables, prefixed with your command name, i.e. for the hello-world example above, before running your program, you can:
export hello_world_stderr=true
Note that you will need to replace '-' in command names with '_' in your environment variables.
Arguments provided on the command line are stored in the 'options._' array. An example can be found here.
In development mode, every meteor app has it's own internal mongodb that is located inside an app's .meteor/local folder.
Therefore, if you want to share a mongodb between your webapp and your command line programs, you will need to use an external mongodb and export the MONGO_URL environment variable so your meteor apps can connect to it. You can get a free sandbox database from compose.io (formerly mongohq), but there are other alternatives out there.
You can execute your commands in a meteor build by appending them to the standard meteor node command line, i.e.
node main.js hello-world --stderr=true
mcli-bundle can be used to test your commands are working in a meteor build before deployment to production, by running:
mcli-bundle hello-world --stderr=true
It will build your meteor program, extract it to a /tmp folder, install the npm packages and run your command, as above. You can also specify a settings file:
mcli-bundle --settings my-settings.json hello-world --stderr=true
In this case, mcli-bundle will automatically set the METEOR_SETTINGS environment variable to the contents of your settings file.
-
Create your meteor app the standard way.
-
Run:
# Meteor command line programs cannot include the webapp package,
# as well as client side packages
meteor remove meteor-platform
# Add the meteor core
meteor add meteor
# Add mongo to access mongodb collections
meteor add mongo
# Add application-configuration to access 3rd party services
meteor add application-configuration
# Add practicalmeteor:mcli
meteor add practicalmeteor:mcli
-
meteor apps expect a main function which is the entry point to the app. The meteor webapp package provides just that. In a cli program, you will need to create your own main function that calls CLI.executeCommand, as in here.
-
Install the jq json command line processor:
# Replace the first line with your linux's distribution way of installing packages.
sudo apt-get install -y jq
- Install the mcli and mcli-bundle tools:
curl https://raw.githubusercontent.com/practicalmeteor/meteor-mcli/master/bin/install-mcli.sh | bash
Since in local development mode, meteor cannot accept command line arguments, the mcli tool creates or extends your meteor settings file and adds the specified command line arguments as an array to Meteor.settings.argv. The practicalmeteor:cli package will read the command line from this setting, if it exists, or the normal way (with some meteor specific manipulation) from process.argv in a meteor build.
Are more than welcome. Would be nice to:
-
Connect to the internal meteor mongodb database of a running meteor app.
-
Start and stop the internal meteor mongodb database, if a meteor app is not running.
-
Have a meteor mcli app scaffolding tool.