Below we provide a more detailed explanation of how to get started. But if you're familiar with node.js and prefer a fast-track:
Install
$ npm i -g {%= name %}
Create an "app"
Then create a basefile.js
with the following code:
module.exports = function(app, base) {
app.task('default', function(cb) {
console.log('task >', this.name);
cb();
});
};
Run base
In the command line, run:
$ base
If everthing installed correctly, you should see task > default
in the command line.
Installing the CLI
To run base from the command line, you'll need to install {%= name %}
globally first. You can that now with the following command:
$ npm i -g {%= name %}
This adds the base
command to your system path, allowing it to be run from any directory or sub-directory in a project.
How the CLI works
When the base
command is run, the globally installed {%= name %}
looks for a locally installed [base][] module using node's require()
system.
If a locally installed [base][] is found, the CLI loads the local installation of the [base][] library. If a local [base][] module is not found, the globally installed base-app
will be used.
Once the module is resolved, base applies the configuration from your basefile.js
then executes any generators or tasks you've specified for base to run.
Getter/setter that ensures the current working directory is always a fully resolved absolute filepath.
app.cwd = 'foo';
console.log(app.cwd);
//=> /User/dev/base-app/foo
Glob patterns or filepaths to source files.
Params
glob
{String|Array}: Glob patterns or file paths to source files.options
{Object}: Options or locals to merge into the context and/or pass tosrc
plugins
Example
app.src('src/*.hbs', {layout: 'default'});
Glob patterns or paths for symlinks.
Params
glob
{String|Array}
Example
app.symlink('src/**');
Specify a destination for processed files.
Params
dest
{String|Function}: File path or rename function.options
{Object}: Options and locals to pass todest
plugins
Example
app.dest('dist/');
Copy files with the given glob patterns
to the specified dest
.
Params
patterns
{String|Array}: Glob patterns of files to copy.dest
{String|Function}: Desination directory.returns
{Stream}: Stream, to continue processing if necessary.
Example
app.task('assets', function(cb) {
app.copy('assets/**', 'dist/')
.on('error', cb)
.on('finish', cb)
});
Methods for running tasks are from the [base-task][] plugin, which uses [composer][]. Additional documentation can be found on those libaries.
Register a task
Params
name
{String}: Task name to register (tasks are cached onapp.tasks
)dependencies
{String|Array|Function}: String, list or array of tasks.callback
{Function}: Function to be called when the task is executed. Task functions should either return a stream or call the callback to let composer know when the task is finished.
Examples
Register a task.
app.task('default', function() {
// return the stream to signal "done"
return app.src('pages/*.hbs')
.pipe(app.dest('dist'));
});
Register a task with dependencies (other tasks to run before executing the task):
app.task('site', ['styles'], function() {
return app.src('pages/*.hbs')
.pipe(app.dest('dist'));
});
app.task('default', ['site']);
Get a task
var task = app.task('site');
Run a task or array of tasks.
Example
app.build('default', function(err, results) {
if (err) {
console.error(err);
return;
}
console.log(results);
});
Compose task or list of tasks into a single function that runs the tasks in series.
Params
tasks
{String|Array|Function}: List of tasks by name, function, or array of names/functions.returns
{Function}: Composed function that may take a callback function.
Example
app.task('foo', function(cb) {
console.log('this is foo');
cb();
});
var fn = app.series('foo', function(cb) {
console.log('this is bar');
cb();
});
fn(function(err) {
if (err) return console.error(err);
console.log('finished');
});
//=> this is foo
//=> this is bar
//=> finished
Compose task or list of tasks into a single function that runs the tasks in parallel.
Params
tasks
{String|Array|Function}: List of tasks by name, function, or array of names/functions.returns
{Function}: Composed function that may take a callback function.
Example
app.task('foo', function(cb) {
setTimeout(function() {
console.log('this is foo');
cb();
}, 500);
});
var fn = app.parallel('foo', function(cb) {
console.log('this is bar');
cb();
});
fn(function(err) {
if (err) return console.error(err);
console.log('finished');
});
//=> this is bar
//=> this is foo
//=> finished
The following events are emitted by [composer][]. See the composer docs for more details
Emitted when a build
is starting.
app.on('starting', function(app, build) {});
The event emits 2 arguments:
- the current instance of [composer][] as the
app
and - An object with
build
runtime information:
.date
: an object with the.start
time as aDate
object..hr
: an object with the.start
time as anhrtime
array.
Emitted when a build
is finished.
app.on('finished', function(app, build) {});
The event emits 2 arguments:
app
: instance of [composer][]build
: an object with build runtime information:
.date
: object with.start
and.end
properties, with staring and ending times of the build asDate
objects..hr
: object with.start
,.end
,.duration
, and.diff
properties with timing information calculated usingprocess.hrtime
Emitted when an error occurrs during a build
.
app.on('error', function(err) {});
Emitted when a task is starting.
app.on('task:starting', function(task, run) {});
Emitted when a task has finished.
app.on('task:finished', function(task, run) {});
Emitted when an error occurrs while running a task.
app.on('task:error', function(err) {});
Register a data loader for loading data onto app.cache.data
.
Params
ext
{String}: The file extension for to match to the loaderfn
{Function}: The loader function.
Example
var yaml = require('js-yaml');
app.dataLoader('yml', function(str, fp) {
return yaml.safeLoad(str);
});
app.data('foo.yml');
//=> loads and parses `foo.yml` as yaml
Define a plugin function to be called immediately upon init. The only parameter exposed to the plugin is the application instance.
Also, if a plugin returns a function, the function will be pushed
onto the fns
array, allowing the plugin to be called at a
later point, elsewhere in the application.
Params
fn
{Function}: plugin function to callreturns
{Object}: Returns the item instance for chaining.
Example
// define a plugin
function foo(app) {
// do stuff
}
// register plugins
var app = new Base()
.use(foo)
.use(bar)
.use(baz)
Run all plugins
Params
value
{Object}: Object to be modified by plugins.returns
{Object}: Returns the item instance for chaining.
Example
var config = {};
app.run(config);
Set or get an option.
Params
key
{String}: The option name.value
{any}: The value to set.returns
{any}: Returns avalue
when onlykey
is defined.
Example
app.option('a', true);
app.option('a');
//=> true
Return true if options.hasOwnProperty(key)
Params
prop
{String}returns
{Boolean}: True ifprop
exists.
Example
app.hasOption('a');
//=> false
app.option('a', 'b');
app.hasOption('a');
//=> true
Enable key
.
Params
key
{String}returns
{Object}Options
: to enable chaining
Example
app.enable('a');
Disable key
.
Params
key
{String}: The option to disable.returns
{Object}Options
: to enable chaining
Example
app.disable('a');
Check if prop
is enabled (truthy).
Params
prop
{String}returns
{Boolean}
Example
app.enabled('a');
//=> false
app.enable('a');
app.enabled('a');
//=> true
Check if prop
is disabled (falsey).
Params
prop
{String}returns
{Boolean}: Returns true ifprop
is disabled.
Example
app.disabled('a');
//=> true
app.enable('a');
app.disabled('a');
//=> false
Returns true if the value of prop
is strictly true
.
Params
prop
{String}returns
{Boolean}: Uses strict equality for comparison.
Example
app.option('a', 'b');
app.isTrue('a');
//=> false
app.option('c', true);
app.isTrue('c');
//=> true
app.option({a: {b: {c: true}}});
app.isTrue('a.b.c');
//=> true
Returns true if the value of key
is strictly false
.
Params
prop
{String}returns
{Boolean}: Uses strict equality for comparison.
Example
app.option('a', null);
app.isFalse('a');
//=> false
app.option('c', false);
app.isFalse('c');
//=> true
app.option({a: {b: {c: false}}});
app.isFalse('a.b.c');
//=> true
Return true if the value of key is either true
or false
.
Params
key
{String}returns
{Boolean}: True iftrue
orfalse
.
Example
app.option('a', 'b');
app.isBoolean('a');
//=> false
app.option('c', true);
app.isBoolean('c');
//=> true
Set option key
on app.options
with the given value
Params
key
{String}: Option key, dot-notation may be used.value
{any}
Example
app.option.set('a', 'b');
console.log(app.option.get('a'));
//=> 'b'
Get option key
from app.options
Params
key
{String}: Option key, dot-notation may be used.returns
{any}
Example
app.option({a: 'b'});
console.log(app.option.get('a'));
//=> 'b'
Returns a shallow clone of app.options
with all of the options methods, as well as a .merge
method for merging options onto the cloned object.
Params
options
{Options}: Object to merge onto the returned options object.returns
{Object}
Example
var opts = app.option.create();
opts.merge({foo: 'bar'});
Load data onto app.cache.data
Params
key
{String|Object}: Key of the value to set, or object to extend.val
{any}returns
{Object}: Returns the instance ofTemplate
for chaining
Example
console.log(app.cache.data);
//=> {};
app.data('a', 'b');
app.data({c: 'd'});
console.log(app.cache.data);
//=> {a: 'b', c: 'd'}
// set an array
app.data('e', ['f']);
// overwrite the array
app.data('e', ['g']);
// update the array
app.data('e', ['h'], true);
console.log(app.cache.data.e);
//=> ['g', 'h']
Shallow extend an object onto app.cache.data
.
Params
key
{String|Object}: Property name or object to extend ontoapp.cache.data
. Dot-notation may be used for extending nested properties.value
{Object}: The object to extend ontoapp.cache.data
returns
{Object}: returns the instance for chaining
Example
app.data({a: {b: {c: 'd'}}});
app.data.extend('a.b', {x: 'y'});
console.log(app.get('a.b'));
//=> {c: 'd', x: 'y'}
Deeply merge an object onto app.cache.data
.
Params
key
{String|Object}: Property name or object to merge ontoapp.cache.data
. Dot-notation may be used for merging nested properties.value
{Object}: The object to merge ontoapp.cache.data
returns
{Object}: returns the instance for chaining
Example
app.data({a: {b: {c: {d: {e: 'f'}}}}});
app.data.merge('a.b', {c: {d: {g: 'h'}}});
console.log(app.get('a.b'));
//=> {c: {d: {e: 'f', g: 'h'}}}
Union the given value onto a new or existing array value on app.cache.data
.
Params
key
{String}: Property name. Dot-notation may be used for nested properties.array
{Object}: The array to add or union onapp.cache.data
returns
{Object}: returns the instance for chaining
Example
app.data({a: {b: ['c', 'd']}});
app.data.union('a.b', ['e', 'f']}});
console.log(app.get('a.b'));
//=> ['c', 'd', 'e', 'f']
Set the given value onto app.cache.data
.
Params
key
{String|Object}: Property name or object to merge ontoapp.cache.data
. Dot-notation may be used for nested properties.val
{any}: The value to set onapp.cache.data
returns
{Object}: returns the instance for chaining
Example
app.data.set('a.b', ['c', 'd']}});
console.log(app.get('a'));
//=> {b: ['c', 'd']}
Get the value of key
from app.cache.data
. Dot-notation may be used for getting nested properties.
Params
key
{String}: The name of the property to get.returns
{any}: Returns the value ofkey
Example
app.data({a: {b: {c: 'd'}}});
console.log(app.get('a.b'));
//=> {c: 'd'}
Glob patterns may be passed as a string or array. All of these work:
app.data('foo.json');
app.data('*.json');
app.data(['*.json']);
// pass options to node-glob
app.data(['*.json'], {dot: true});
Namespacing allows you to load data onto a specific key, optionally using part of the file path as the key.
Example
Given that foo.json
contains {a: 'b'}
:
app.data('foo.json');
console.log(app.cache.data);
//=> {a: 'b'}
app.data('foo.json', {namespace: true});
console.log(app.cache.data);
//=> {foo: {a: 'b'}}
app.data('foo.json', {
namespace: function(fp) {
return path.basename(fp);
}
});
console.log(app.cache.data);
//=> {'foo.json': {a: 'b'}}