Skip to content
Tyler Kellen edited this page Nov 21, 2013 · 22 revisions

basic specification

Perform an arbitrary task.

Modules which implement the basic node-task specification must provide a constructor which can be called to create a unique instance of an object with the following API. All methods and properties are optional with the exception of the run method.

description

A short description of the job the task will perform.

version

A valid semver string.

options

If a task allows options, they must be enumerated under this property as an object where the key is the option name and the value is an object which contains, at a minimum, key/value pairs for description and defaultValue. This property is primarily intended for task runner introspection, but authors are encouraged to use it for applying default values in parseConfig.

emitter

A EventEmitter2 instance with wildcard support. In order to allow parallel execution by task runners, a unique instance must be provided when the task is instantiated.

emit(emit, arg1, arg2, ...)

A convenience method for emitting on an optionally underlying EventEmitter2 instance.

run(config, input)

Execute a task, returning a promise representing its completion. Config should be an object holding the task configuration. If a task has input, it must arrive in a compatible Input Format.

If input is supplied, this method must return a promise which resolves to the input object to allow it to be chained. Task authors should expect the Input Format will contain Record sources, as produced by prepare (or another compatible task).

chain(config)

Partial application convenience method to facilitate task chaining. Should return a function which takes a single argument, input, which executes the run method with config applied. For a real world usage of this method, see pipeliner.

Task.prototype.chain = function (config) {
  return function (input) {
    return this.run(config, input);
  }.bind(this);
};

parseConfig(config)

Normalize task configuration, returning the modified config with any defaults from options applied. This method must be synchronous.

setup(config)

Pre-task operations, if any, occur here.

teardown(config)

Post-task operations, if any, occur here.

Examples

While the following examples meet the requirements of the basic spec, they should not be considered the only correct way to implement a compliant module. Developers will undoubtedly provide builders to facilitate the creation of tasks. See a sample generator here.

A minimal compliant module:

var when = require('when');
var Task = function Task() {};
Task.prototype.run = function (config) {
  return when(true);
};
module.exports = Task;

A more comprehensive implementation:

var when = require('when');
var EventEmitter2 = require('eventemitter2').EventEmitter2;
var _ = require('lodash');

var Task = function Task() {
  this.emitter = new EventEmitter2({wildcard: true});
};

Task.prototype.name = 'example';
Task.prototype.description = 'fake task using all spec properties and methods';
Task.prototype.version = '0.1.0';
Task.prototype.options = {
  debug: {
    description: "debug mode",
    defaultValue: false
  },
  fake: {
    description: "a fake option",
    defaultValue: 1
  }
};
Task.prototype.emit = function() {
  this.emitter.emit.apply(this.emitter, arguments);
};
Task.prototype.parseConfig = function (config) {
  var defaults = _.merge({}, this.options||{}, function(d, o) {
    return o.defaultValue;
  });
  return _.extend(defaults, config);
};
Task.prototype.run = function (config, input) {
  var runConfig = this.parseConfig(config);
  return when(true);
};
Task.prototype.chain = function (config) {
  return function (input) {
    return this.run(config, input);
  }.bind(this);
};
Task.prototype.setup = function (config) {
};
Task.prototype.teardown = function (config) {
};
module.exports = Task;
Clone this wiki locally