Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the basic node-task specification #17

Open
yuanyan opened this issue May 8, 2013 · 0 comments
Open

Implement the basic node-task specification #17

yuanyan opened this issue May 8, 2013 · 0 comments
Labels
Milestone

Comments

@yuanyan
Copy link
Contributor

yuanyan commented May 8, 2013

https://github.com/node-task/spec/wiki/Task

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.

name

A single word name for task.

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.

on(event, listener)

An EventEmitter2 compatible on method. In order to allow parallel execution by task runners, this method must assign listeners to a unique instance of the underlying emitter. Must support wildcards.

off(event, listener)

An EventEmitter2 compatible off method. In order to allow parallel execution by task runners, this method must remove listeners from a unique instance of the underlying emitter. Must support wildcards.

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

An EventEmitter2 compatible emit method. In order to allow parallel execution by task runners, this method must emit events from a unique instance of the underlying emitter.

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 util = require('util');
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.on = function() {
  this.emitter.on.apply(this, arguments);
};
Task.prototype.off = function() {
  this.emitter.off.apply(this, arguments);
};
Task.prototype.emit = function() {
  this.emitter.emit.apply(this, arguments);
};
Task.prototype.parseConfig = function (config) {
  this.emit('debug.parseConfig', config);
  var defaults = _.merge({}, this.options||{}, function(d, o) {
    return o.defaultValue;
  });
  return _.extend(defaults, config);
};
Task.prototype.run = function (config, input) {
  this.emit('debug.run', runConfig);
  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) {
  this.emit('debug.setup', config);
};
Task.prototype.teardown = function (config) {
  this.emit('debug.teardown', config);
};
module.exports = Task;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant