Javascript API
Roots v3 has been built from the ground up to have a strong js API, which is significantly different from all previous versions of roots. Let's walk through it here.
Creating a new Roots
instance
There are two ways you can create a new instance of the Roots
class - first using the traditional constructor, which expects a path that contains a roots project, and second with the Roots.new
class method. Let's take a look at both here.
First, let's look at the more traditional constructor:
var Roots = require('roots'),
path = require('path');
var project = new Roots(path.join(__dirname, 'example-project'));
As you can can see here, roots is initialized with a path pointing to the project root. You can also pass a second optional parameter specifying options for the project, which are documented here. Note that the path passed to the constructor must already exist, or roots will throw an error.
Now let's check out the Roots.new
alternate constructor. This method will create a roots project from a template at a given path, then return an instance. However, since it involves quite a bit of I/O, it is also asynchrnonous. The Roots.new
method itself returns a promise, which, if fulfilled, will return an initialized roots instance. Since it's a lengthy process, the promise also returns progress events along the way. Below is an example of how it could be used:
var Roots = require('roots'),
path = require('path');
Roots.new({
// directory can not yet exist
path: path.join(__dirname, 'example-project'),
// optional - defaults to 'roots-base'
template: 'roots-base',
// optional - data to pass to template
overrides: { description: 'foobar' }
}).progress(function(message){
// ex: 'progress: dependencies installing'
console.log('progress: ' + message);
}).done(function(project){
console.log(project); // new roots project instance
}, function(err){
console.error("oh no! " + err);
});
Note that the path you pass to this constructor should not exist, a folder will be created there. If a folder already exists at that path, it will be filled with the files from the template, which probably is not what you want.
Compiling a Project
To compile a roots project once, you can use the compile
method, which is fairly straightforward and returns a promise for the compiled project if you need it. Below is a quick example of loading in a roots project and compiling it:
var Roots = require('roots');
var project = new Roots('/path/to/project');
project
.on('error') // compile error
.on('done'); // compile is finished
project.compile();
Here we use the event emitter interface to listen for events and determine what's going on. As mentioned above, the compile method itself also returns a promise for the finished compilation process. So if you aren't concerned with the events and rather just know if it's finished or if there was an error, you could run code like this:
var Roots = require('roots');
var project = new Roots('/path/to/project');
project.compile().then(successFn, errorFn);
This will work fine, and fit nicely into any existant promise chain. The promise compile
returns is A+ compliant and generated by the latest version of when.js.
Watching a Project
You can also watch through the public API, but beware -- while watching, there is currently no way to stop the process other than exiting it manually. It returns your instance like compile
and you can listen for the same events:
var Roots = require('roots');
var project = new Roots('/path/to/project');
project
.on('error')
.on('done');
project.watch();
If you need to cancel the watcher at any time, the actual watch
method returns a chokidar watcher instance, which you can call .close()
on to stop the watcher. For example:
var Roots = require('roots');
var project = new Roots('/path/to/project');
project
.on('error')
.on('done')
var watcher = project.watch();
setTimeout(watcher.close, 1000);
This code would, for some reason, start a watcher but stop it after 1 second. You get the idea.