UNPKG

masson

Version:

Module execution engine for cluster deployments.

259 lines (226 loc) 6.31 kB
// Generated by CoffeeScript 1.7.1 var EventEmitter, Tree, crypto, flatten, load, util; crypto = require('crypto'); util = require('util'); EventEmitter = require('events').EventEmitter; load = require('./load'); flatten = require('./misc').flatten; /* Tree ==== Build a tree with all the actions to execute from a list of modules. Action properties: - `hidden` Visibility of the action name - `name` Name of the action - `module` Module where the action is defined - `index` Position of the action inside the module Example using a callback tree = require './tree' tree modules, (err, actions) -> util.print actions Example using the EventEmitter API: tree.actions(modules, options) .on 'module', (location) -> util.print 'module', location .on 'action', (action) -> util.print 'action', action .on 'end', (actions) -> util.print actions .on 'error', (err) -> util.print err */ Tree = function(modules, options) { return this; }; util.inherits(Tree, EventEmitter); /* Build a run list for the given modules. Options include: - `modules` Only return this module and its dependencies - `fast` Skip dependencies - `all` Return the full list of actions, work with the `module` and `fast` options */ Tree.prototype.actions = function(modules, options, callback) { var ev; if (typeof options === 'function') { callback = options; options = {}; } if (typeof options.modules === 'string') { options.modules = [options.modules]; } if (!Array.isArray(options.modules)) { options.modules = []; } ev = new EventEmitter; setImmediate((function(_this) { return function() { var action, actions, err, leaf, tree, _i, _j, _len, _len1, _ref; if (!Array.isArray(modules)) { modules = [modules]; } modules = flatten(modules); try { tree = _this.load_tree(modules); } catch (_error) { err = _error; ev.emit('error', err); callback(err); return; } if (options.modules.length) { modules = tree.map(function(leaf) { return leaf.module; }); modules = options.modules.filter(function(module) { return modules.indexOf(module) !== -1; }); tree = _this.load_tree(modules); if (options.fast) { tree = tree.filter(function(leaf) { if (options.modules.indexOf(leaf.module) !== -1) { return true; } leaf.actions = leaf.actions.filter(function(action) { return action.required; }); return leaf.actions.length; }); } } actions = []; for (_i = 0, _len = tree.length; _i < _len; _i++) { leaf = tree[_i]; ev.emit('module', leaf.module); _ref = leaf.actions; for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { action = _ref[_j]; ev.emit('action', action); actions.push(action); } } ev.emit('end', actions); if (callback) { return callback(null, actions); } }; })(this)); return ev; }; Tree.prototype.modules = function(modules, options, callback) { var mods; mods = []; return this.actions(modules, options).on('module', function(module) { return mods.push(module); }).on('error', function(err) { return callback(err); }).on('end', function() { return callback(null, mods); }); }; /* Return a array of object with the module name and its associated actions */ Tree.prototype.load_tree = function(modules) { var build_tree, called, module, tree, _i, _len; called = {}; tree = []; build_tree = (function(_this) { return function(module) { var action, leaf, _i, _len, _ref; if (called[module]) { return; } called[module] = true; leaf = { module: module, actions: [] }; _ref = _this.load_module(module); for (_i = 0, _len = _ref.length; _i < _len; _i++) { action = _ref[_i]; if (typeof action === 'string') { if (leaf.actions.length) { tree.push(leaf); } leaf = { module: module, actions: [] }; build_tree(action); } else { leaf.actions.push(action); } } return tree.push(leaf); }; })(this); for (_i = 0, _len = modules.length; _i < _len; _i++) { module = modules[_i]; build_tree(module); } return tree; }; /* Load a module and return its actions. Module actions when defining a string dependency may be prefixed with: * "?": Load this module only if it is defined by the user in the run list. * "!": Force this module to be loaded and executed, apply to "fast" mode. */ Tree.prototype.load_module = function(module) { var actions, callback, i, meta, required, _, _i, _len, _ref; if (this.cache == null) { this.cache = {}; } if (this.cache[module]) { return this.cache[module]; } required = false; _ref = /([\!\?]?)(.*)/.exec(module), _ = _ref[0], meta = _ref[1], module = _ref[2]; switch (meta) { case '?': break; case '!': required = true; } actions = load(module); if (!Array.isArray(actions)) { actions = [actions]; } for (i = _i = 0, _len = actions.length; _i < _len; i = ++_i) { callback = actions[i]; if (typeof callback === 'string') { continue; } if (typeof callback === 'function') { callback = actions[i] = { callback: callback }; } if (!callback.name) { if (callback.hidden == null) { callback.hidden = true; } } if (callback.name == null) { callback.name = "" + module + "/" + i; } if (callback.module == null) { callback.module = module; } if (callback.index == null) { callback.index = i; } if (callback.skip == null) { callback.skip = false; } if (required) { callback.required = true; } } return this.cache[module] = actions; }; module.exports = function(modules, options, callback) { return (new Tree).actions(modules, options, callback); }; module.exports.Tree = Tree;