base-app

Starting point for creating a base application, with a few light plugins for running tasks and writing to the file system, and a functional CLI.
Please consider following this project's author, Jon Schlinkert, and consider starring the project to show your :heart: and support.
(TOC generated by verb using markdown-toc)
Install
Install with npm:
$ npm install --save base-app
Quickstart
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 base-app
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.
CLI
Installing the CLI
To run base from the command line, you'll need to install base-app globally first. You can that now with the following command:
$ npm i -g base-app
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 base-app 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.
.cwd
Getter/setter that ensures the current working directory is always a fully resolved absolute filepath.
app.cwd = 'foo';
console.log(app.cwd);
File System API
.src
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 to src plugins
Example
app.src('src/*.hbs', {layout: 'default'});
.symlink
Glob patterns or paths for symlinks.
Params
Example
app.symlink('src/**');
.dest
Specify a destination for processed files.
Params
dest {String|Function}: File path or rename function.
options {Object}: Options and locals to pass to dest plugins
Example
app.dest('dist/');
.copy
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)
});
Task API
Methods for running tasks are from the base-task plugin, which uses composer. Additional documentation can be found on those libaries.
.task
Register a task
Params
name {String}: Task name to register (tasks are cached on app.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 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');
.build
Run a task or array of tasks.
Example
app.build('default', function(err, results) {
if (err) {
console.error(err);
return;
}
console.log(results);
});
.series
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');
});
.parallel
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');
});
Events
The following events are emitted by composer. See the composer docs for more details
starting
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 a Date object.
.hr: an object with the .start time as an hrtime array.
finished
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 as Date objects.
.hr: object with .start, .end, .duration, and .diff properties with timing information calculated using process.hrtime
error
Emitted when an error occurrs during a build.
app.on('error', function(err) {});
task:starting
Emitted when a task is starting.
app.on('task:starting', function(task, run) {});
task:finished
Emitted when a task has finished.
app.on('task:finished', function(task, run) {});
task:error
Emitted when an error occurrs while running a task.
app.on('task:error', function(err) {});
.dataLoader
Register a data loader for loading data onto app.cache.data.
Params
ext {String}: The file extension for to match to the loader
fn {Function}: The loader function.
Example
var yaml = require('js-yaml');
app.dataLoader('yml', function(str, fp) {
return yaml.safeLoad(str);
});
app.data('foo.yml');
Plugin API
.use
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 call
returns {Object}: Returns the item instance for chaining.
Example
function foo(app) {
}
var app = new Base()
.use(foo)
.use(bar)
.use(baz)
.run
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);
Options API
.option
Set or get an option.
Params
key {String}: The option name.
value {any}: The value to set.
returns {any}: Returns a value when only key is defined.
Example
app.option('a', true);
app.option('a');
.hasOption
Return true if options.hasOwnProperty(key)
Params
prop {String}
returns {Boolean}: True if prop exists.
Example
app.hasOption('a');
app.option('a', 'b');
app.hasOption('a');
.enable
Enable key.
Params
key {String}
returns {Object} Options: to enable chaining
Example
app.enable('a');
.disable
Disable key.
Params
key {String}: The option to disable.
returns {Object} Options: to enable chaining
Example
app.disable('a');
.enabled
Check if prop is enabled (truthy).
Params
prop {String}
returns {Boolean}
Example
app.enabled('a');
app.enable('a');
app.enabled('a');
.disabled
Check if prop is disabled (falsey).
Params
prop {String}
returns {Boolean}: Returns true if prop is disabled.
Example
app.disabled('a');
app.enable('a');
app.disabled('a');
.isTrue
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');
app.option('c', true);
app.isTrue('c');
app.option({a: {b: {c: true}}});
app.isTrue('a.b.c');
.isFalse
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');
app.option('c', false);
app.isFalse('c');
app.option({a: {b: {c: false}}});
app.isFalse('a.b.c');
.isBoolean
Return true if the value of key is either true or false.
Params
key {String}
returns {Boolean}: True if true or false.
Example
app.option('a', 'b');
app.isBoolean('a');
app.option('c', true);
app.isBoolean('c');
.option.set
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'));
.option.get
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'));
.option.create
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'});
Data API
.data
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 of Template for chaining
Example
console.log(app.cache.data);
app.data('a', 'b');
app.data({c: 'd'});
console.log(app.cache.data);
app.data('e', ['f']);
app.data('e', ['g']);
app.data('e', ['h'], true);
console.log(app.cache.data.e);
.data.extend
Shallow extend an object onto app.cache.data.
Params
key {String|Object}: Property name or object to extend onto app.cache.data. Dot-notation may be used for extending nested properties.
value {Object}: The object to extend onto app.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'));
.data.merge
Deeply merge an object onto app.cache.data.
Params
key {String|Object}: Property name or object to merge onto app.cache.data. Dot-notation may be used for merging nested properties.
value {Object}: The object to merge onto app.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'));
.data.union
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 on app.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'));
.data.set
Set the given value onto app.cache.data.
Params
key {String|Object}: Property name or object to merge onto app.cache.data. Dot-notation may be used for nested properties.
val {any}: The value to set on app.cache.data
returns {Object}: returns the instance for chaining
Example
app.data.set('a.b', ['c', 'd']}});
console.log(app.get('a'));
.data.get
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 of key
Example
app.data({a: {b: {c: 'd'}}});
console.log(app.get('a.b'));
Glob patterns
Glob patterns may be passed as a string or array. All of these work:
app.data('foo.json');
app.data('*.json');
app.data(['*.json']);
app.data(['*.json'], {dot: true});
Namespacing
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);
app.data('foo.json', {namespace: true});
console.log(app.cache.data);
app.data('foo.json', {
namespace: function(fp) {
return path.basename(fp);
}
});
console.log(app.cache.data);
About
Contributing
Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.
Running Tests
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
$ npm install && npm test
Building docs
(This project's readme.md is generated by verb, please don't edit the readme directly. Any changes to the readme must be made in the .verb.md readme template.)
To generate the readme, run the following command:
$ npm install -g verbose/verb
Related projects
You might also be interested in these projects:
- base-fs: base-methods plugin that adds vinyl-fs methods to your 'base' application for working with the file… more | homepage
- base-pipeline: base-methods plugin that adds pipeline and plugin methods for dynamically composing streaming plugin pipelines. | homepage
- base: Framework for rapidly creating high quality, server-side node.js applications, using plugins like building blocks | homepage
Author
Jon Schlinkert
License
Copyright © 2018, Jon Schlinkert.
Released under the MIT License.
This file was generated by verb-generate-readme, v0.6.0, on April 13, 2018.