<commit_before>
/**
 * @file
 */

/**
 * Print all tickers into the ticker bar.
 *
 * This may be called multiple times due to the async nature of fetching
 * the metrics. Be prepared cache items that don't exist yet.
 */
var showBar = function(variables) {

    if (variables.length) {
        var markup = '
';
        markup = markup + '<cst-bar variables="variables" orient="\'horizontal\'" ng-init="variables=[\'' + variables.join('\',\'') + '\']"></cst-bar>';
        markup = markup + '
';
        $('body').append(markup);
        $('html').css('position', 'relative');
        $('html').css({'margin-top':'30px'});
        var element = $('#cst-tickerbar');
        angular.bootstrap(element, ['chromeStockTicker']);
    }
};

var findVariables = function(html, patterns) {
    var symbols = [];
    // Iterate through all 'a' elements.
    $(html).find('a').each(function() {
        var href = $(this).attr('href');
        // If the element has a 'href' attribute.
        if (typeof(href) != 'undefined') {
            try {
                href = decodeURIComponent(href);
                for (var i=0; i<patterns.items.length; i++) {
                    var match;
                    var regex = new RegExp(patterns.items[i].regex, patterns.items[i].modifiers);
                    // If the href attribute matches one of our patterns.
                    while ((match = regex.exec(href)) !== null) {
                        symbols.push(match[patterns.items[i].result].toUpperCase());
                    }
                }
            } catch (err) {
                console.log('Can not examine href (' + href + '): ' + err);
            }
        }
    });
    // Remove any duplicates.
    var symbolsCleaned = [];
    $.each(symbols, function(i, el) {
        if($.inArray(el, symbolsCleaned) === -1) symbolsCleaned.push(el);
    });
    return symbolsCleaned;
};

/**
 * Load a JS library; if it does not already exist in content context.
 *
 * All js files must be included in the manifest's web_accessible_resources.
 *
 * @param string file
 *   Name of the local javascript file to load.
 * @param array regex
 *   (optional) An array of Regular expression objects. If present will only
 *   load file if the content page does not have a script element with a src
 *   attribute that matches regex pattern. If ommited then the file will
 *   always be loaded.
 *
 * @return null;
 */
var cstLoadJS = function(file, regex) {
    var load = function(file) {
        $.get(chrome.extension.getURL(file), {}, function(data) {
            eval(data);
        });
    }
    var found = false;
    if (typeof(regex) != 'undefined') {
        for (var i in regex) {
            $('script').each(function(index, element) {
                var src = $(element).attr('src');
                if (src && src.match(regex[i])) {
                    found = true;
                    return false;
                }
            });
            if (found)
                break;
        }
        if (found)
            console.log(file + " Is already present!");
        if (!found)
            load(file);
    } else {
        load(file);
    }
}

/**
 * Load all JS libraries.
 *
 * It is neccesary to dynamically load all libraries rather than specifying
 * them to auto load in the manifest file. Certail libraries should only be
 * loaded conditionally, if they do not already exist in the content context.
 * Double loading these libraries will break the content page, which is the
 * last thing we want to do. Better to break our extension in these cases.
 *
 * The JS is isolated between contexs (content and tab(extension)), but the
 * DOM is shared. Any libraries that automatically operate on the DOM will
 * cause difficulty when loaded twice and working with a shared DOM.
 *
 * @return null;
 */
var cstLoadAllJS = function() {
    var conditionalJs = [
        { file: "libs/external/bootstrap/bootstrap-3.0.3/dist/js/bootstrap.min.js", regex: [ /bootstrap(?:\.min)?\.js/ ] }
    ];
    var alwaysJs = [
        "libs/external/angular/angular.min.js",
        "libs/external/bower_components/angular-ui-utils/ui-utils.min.js",
        "libs/CSTResource.js",
        "js/cstApp.js",
        "js/resource/resourceFactory.js",
        "js/links/linksFactory.js",
        "js/links/linksCtrl.js",
        "js/links/linksDirective.js",
        "js/variable/variableCtrl.js",
        "js/variable/variableDirective.js",
        "js/variable/variableFactory.js",
        "js/bar/barCtrl.js",
        "js/bar/barDirective.js",
        "js/pattern/patternCtrl.js",
        "js/pattern/patternDirective.js"
    ];
    for (var i in conditionalJs)
        cstLoadJS(conditionalJs[i].file, conditionalJs[i].regex);
    for (var i in alwaysJs)
        cstLoadJS(alwaysJs[i]);
}

$('document').ready(function() {
    cstLoadAllJS();
    chrome.storage.sync.get(['patterns'], function(result) {
        if (chrome.runtime.lastError) {
            console.log('Content script can\'t read from synced storage: ' + chrome.runtime.lastError.message);
        }
        var variables = findVariables($('html').html(), result['patterns']);
        showBar(variables);
    });
});
<commit_msg>Made $.get blocking while loading local JS files.<commit_after>
/**
 * @file
 */

/**
 * Print all tickers into the ticker bar.
 *
 * This may be called multiple times due to the async nature of fetching
 * the metrics. Be prepared cache items that don't exist yet.
 */
var showBar = function(variables) {

    if (variables.length) {
        var markup = '
';
        markup = markup + '<cst-bar variables="variables" orient="\'horizontal\'" ng-init="variables=[\'' + variables.join('\',\'') + '\']"></cst-bar>';
        markup = markup + '
';
        $('body').append(markup);
        $('html').css('position', 'relative');
        $('html').css({'margin-top':'30px'});
        var element = $('#cst-tickerbar');
        angular.bootstrap(element, ['chromeStockTicker']);
    }
};

var findVariables = function(html, patterns) {
    var symbols = [];
    // Iterate through all 'a' elements.
    $(html).find('a').each(function() {
        var href = $(this).attr('href');
        // If the element has a 'href' attribute.
        if (typeof(href) != 'undefined') {
            try {
                href = decodeURIComponent(href);
                for (var i=0; i<patterns.items.length; i++) {
                    var match;
                    var regex = new RegExp(patterns.items[i].regex, patterns.items[i].modifiers);
                    // If the href attribute matches one of our patterns.
                    while ((match = regex.exec(href)) !== null) {
                        symbols.push(match[patterns.items[i].result].toUpperCase());
                    }
                }
            } catch (err) {
                console.log('Can not examine href (' + href + '): ' + err);
            }
        }
    });
    // Remove any duplicates.
    var symbolsCleaned = [];
    $.each(symbols, function(i, el) {
        if($.inArray(el, symbolsCleaned) === -1) symbolsCleaned.push(el);
    });
    return symbolsCleaned;
};

/**
 * Load a JS library; if it does not already exist in content context.
 *
 * All js files must be included in the manifest's web_accessible_resources.
 *
 * @param string file
 *   Name of the local javascript file to load.
 * @param array regex
 *   (optional) An array of Regular expression objects. If present will only
 *   load file if the content page does not have a script element with a src
 *   attribute that matches regex pattern. If ommited then the file will
 *   always be loaded.
 *
 * @return null;
 */
var cstLoadJS = function(file, regex) {
    var load = function(file) {
        $.get(chrome.extension.getURL(file), {}, function(data) {
            eval(data);
        });
    }
    var found = false;
    if (typeof(regex) != 'undefined') {
        for (var i in regex) {
            $('script').each(function(index, element) {
                var src = $(element).attr('src');
                if (src && src.match(regex[i])) {
                    found = true;
                    return false;
                }
            });
            if (found)
                break;
        }
        if (found)
            console.log(file + " Is already present!");
        if (!found)
            load(file);
    } else {
        load(file);
    }
}

/**
 * Load all JS libraries.
 *
 * It is neccesary to dynamically load all libraries rather than specifying
 * them to auto load in the manifest file. Certail libraries should only be
 * loaded conditionally, if they do not already exist in the content context.
 * Double loading these libraries will break the content page, which is the
 * last thing we want to do. Better to break our extension in these cases.
 *
 * The JS is isolated between contexs (content and tab(extension)), but the
 * DOM is shared. Any libraries that automatically operate on the DOM will
 * cause difficulty when loaded twice and working with a shared DOM.
 *
 * @return null;
 */
var cstLoadAllJS = function() {
    var conditionalJs = [
        { file: "libs/external/bootstrap/bootstrap-3.0.3/dist/js/bootstrap.min.js", regex: [ /bootstrap(?:\.min)?\.js/ ] }
    ];
    var alwaysJs = [
        "libs/external/angular/angular.min.js",
        "libs/external/bower_components/angular-ui-utils/ui-utils.min.js",
        "libs/CSTResource.js",
        "js/cstApp.js",
        "js/resource/resourceFactory.js",
        "js/links/linksFactory.js",
        "js/links/linksCtrl.js",
        "js/links/linksDirective.js",
        "js/variable/variableCtrl.js",
        "js/variable/variableDirective.js",
        "js/variable/variableFactory.js",
        "js/bar/barCtrl.js",
        "js/bar/barDirective.js",
        "js/pattern/patternCtrl.js",
        "js/pattern/patternDirective.js"
    ];
    // Ensure that we load this in the correct order.
    $.ajaxSetup({async:false});
    for (var i in conditionalJs)
        cstLoadJS(conditionalJs[i].file, conditionalJs[i].regex);
    for (var i in alwaysJs)
        cstLoadJS(alwaysJs[i]);
    $.ajaxSetup({async:true});
}

$('document').ready(function() {
    cstLoadAllJS();
    chrome.storage.sync.get(['patterns'], function(result) {
        if (chrome.runtime.lastError) {
            console.log('Content script can\'t read from synced storage: ' + chrome.runtime.lastError.message);
        }
        var variables = findVariables($('html').html(), result['patterns']);
        showBar(variables);
    });
});
<|endoftext|>


<commit_before>
/*
Copyright (c) 2012, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/

var path = require('path'),
    url = require('url');

// url(../../foo.png)
var URL_REGEX = "(?:(url\\s*\\(\\s*)([^\\s\\)]+))";

// AlphaImageLoader(src='picker_mask.png')
var ALPHA_IMAGE_LOADER_REGEX = "(?:(AlphaImageLoader\\s*\\(\\s*src\\=)([^,\\s\\)]+))|(?:(AlphaImageLoader\\s*\\(.*?src\\=)([^,\\s\\)]+))";

var REGEX_FIND = new RegExp(URL_REGEX + '|' + ALPHA_IMAGE_LOADER_REGEX, 'gim');
var REGEX_PARSE = new RegExp(URL_REGEX + '|' + ALPHA_IMAGE_LOADER_REGEX, 'i');

var normalize = function(options, str, m) {
    var top, resolved, relative, URI,
        quote, item, baseItem = m[0];

    item = m[6] || m[4] || m[2];
    quote = item.substr(0, 1);
    if (quote && (quote === '"' || quote === "'")) {
        item = item.substr(1);
        item = item.substr(0, item.length - 1);
    }
    if (!item.match(/^https?:\/\//) && (item.indexOf('.') > -1)) {
        URI = url.parse(options.base);
        top = path.dirname(options.path);
        resolved = path.resolve(top, item);
        relative = resolved;

        if (item.charAt(0) !== '/') {
            relative = path.relative(options.root, resolved);
        }

        // Windows root directory handling.
        if (process.env.OS === 'Windows_NT' && relative.substr(1, 2) === ':\\') {
            relative = relative.substr(2);
        }

        expanded = URI.protocol + '//' + URI.hostname + path.join(URI.pathname, relative).replace(/\\\\|\\/g, '/');

        str = str.replace(baseItem, baseItem.replace(item, expanded));
    }
    return str;
};

exports.parse = function(options, str, callback) {

    var items = str.match(REGEX_FIND);

    if (Array.isArray(items)) {
        items.forEach(function(matcher) {
            var m = matcher.match(REGEX_PARSE);
            str = normalize(options, str, m);
        });
    }

    callback(null, str);
};
<commit_msg>Refixing #1 with process.platform, thanks @evocateur<commit_after>
/*
Copyright (c) 2012, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/

var path = require('path'),
    url = require('url');

// url(../../foo.png)
var URL_REGEX = "(?:(url\\s*\\(\\s*)([^\\s\\)]+))";

// AlphaImageLoader(src='picker_mask.png')
var ALPHA_IMAGE_LOADER_REGEX = "(?:(AlphaImageLoader\\s*\\(\\s*src\\=)([^,\\s\\)]+))|(?:(AlphaImageLoader\\s*\\(.*?src\\=)([^,\\s\\)]+))";

var REGEX_FIND = new RegExp(URL_REGEX + '|' + ALPHA_IMAGE_LOADER_REGEX, 'gim');
var REGEX_PARSE = new RegExp(URL_REGEX + '|' + ALPHA_IMAGE_LOADER_REGEX, 'i');

var normalize = function(options, str, m) {
    var top, resolved, relative, URI,
        quote, item, baseItem = m[0];

    item = m[6] || m[4] || m[2];
    quote = item.substr(0, 1);
    if (quote && (quote === '"' || quote === "'")) {
        item = item.substr(1);
        item = item.substr(0, item.length - 1);
    }
    if (!item.match(/^https?:\/\//) && (item.indexOf('.') > -1)) {
        URI = url.parse(options.base);
        top = path.dirname(options.path);
        resolved = path.resolve(top, item);
        relative = resolved;

        if (item.charAt(0) !== '/') {
            relative = path.relative(options.root, resolved);
        }

        // Windows root directory handling.
        if (process.platform === 'win32' && relative.substr(1, 2) === ':\\') {
            relative = relative.substr(2);
        }

        expanded = URI.protocol + '//' + URI.hostname + path.join(URI.pathname, relative).replace(/\\\\|\\/g, '/');

        str = str.replace(baseItem, baseItem.replace(item, expanded));
    }
    return str;
};

exports.parse = function(options, str, callback) {

    var items = str.match(REGEX_FIND);

    if (Array.isArray(items)) {
        items.forEach(function(matcher) {
            var m = matcher.match(REGEX_PARSE);
            str = normalize(options, str, m);
        });
    }

    callback(null, str);
};
<|endoftext|>


<commit_before>// [node-http2](https://github.com/molnarg/node-http2) consists of the following components:

// * [http.js](http.html): public node-http2 API
var http2        = require('./http');
module.exports = http2;

// * [logging.js](logging.html): a default logger object and a registry of log formatter functions
http2.logging    = require('./logging');

// * [framer.js](framer.html): the lowest layer in the stack that transforms between the binary and
//   the JavaScript object representation of HTTP/2 frames
http2.framer     = require('./framer');

// * [compressor.js](compressor.html): compression and decompression of HEADER frames
http2.compressor = require('./compressor');

// * [stream.js](stream.html): implementation of the HTTP/2 stream concept
http2.stream     = require('./stream');

// * [connection.js](connection.html): multiplexes streams, manages the identifiers of them and
//   repsonsible for connection level flow control
http2.connection = require('./connection');

// * [endpoint.js](endpoint.html): manages other components (framer, compressor, connection,
//   streams) and part of the handshake process
http2.endpoint   = require('./endpoint');
<commit_msg>Index: adding Flow to the index.<commit_after>// [node-http2](https://github.com/molnarg/node-http2) consists of the following components:

// * [http.js](http.html): public node-http2 API
var http2        = require('./http');
module.exports   = http2;

// * [logging.js](logging.html): a default logger object and a registry of log formatter functions
http2.logging    = require('./logging');

// * [framer.js](framer.html): the lowest layer in the stack that transforms between the binary and
//   the JavaScript object representation of HTTP/2 frames
http2.framer     = require('./framer');

// * [compressor.js](compressor.html): compression and decompression of HEADER frames
http2.compressor = require('./compressor');

// * [flow.js](flow.html): flow control
http2.flow       = require('./flow');

// * [stream.js](stream.html): implementation of the HTTP/2 stream concept
http2.stream     = require('./stream');

// * [connection.js](connection.html): multiplexes streams, manages the identifiers of them and
//   repsonsible for connection level flow control
http2.connection = require('./connection');

// * [endpoint.js](endpoint.html): manages other components (framer, compressor, connection,
//   streams) and part of the handshake process
http2.endpoint   = require('./endpoint');
<|endoftext|>


<commit_before>export default function(patterns, callback) {
    return function watch(resolve, reject) {
        const chokidar = require('chokidar');

        function call(file) {
            callback(file).catch(reject);
        }

        chokidar
            .watch(patterns, { persistent: true })
            .on('change', callback)
            .on('add', callback)
            .on('error', reject);

        callback(patterns);
    };
}
<commit_msg>:wrench: listen for `add` and `addDir` events<commit_after>export default function(patterns, callback) {
    return function watch(resolve, reject) {
        const chokidar = require('chokidar');

        const watcher = chokidar
            .watch(patterns, { persistent: true })
            .on('change', callback)
            .on('ready', function() {
                watcher.on('add', callback);
                watcher.on('addDir', callback);
            })
            .on('error', reject);

        function afterInitial() {
            resolve('press CTRL+C to exit');
        }

        callback(patterns)
            .then(afterInitial)
            .catch(afterInitial);
    };
}
<|endoftext|>


<commit_before>var Ul = require("ul");
var Typpy = require("typpy");
var Deffy = require("deffy");

const TYPES = {
    event: "event",
    dataHandler: "dataHandler",
    errorHandler: "errorHandler",
    streamHandler: "streamHandler",
    load: "load",
    emit: "emit",
    link: "link",
    listener: "listener"
};

function Enny() {
    var self = this;
    self.instances = {};
    self.Instance = function (data) {
        return new Enny.Instance(data, {
            enny: self
        });
    };
    self.FlowComponent = function (data) {
        return new Enny.FlowComponent(data, {
            enny: self
        });
    };
}

Enny.prototype.toJSON = function (a, b, c) {
    var self = this;
    var obj = {};
    Object.keys(self.instances).forEach(function (name) {
        obj[name] = self.instances[name]._;
    });
    return obj;
};

Enny.prototype.addInstance = function (ins) {
    ins = this.Instance(ins);
    this.instances[ins._.name] = ins;
    return ins;
};

Enny.Instance = function Instance (data, options) {
    if (Typpy(data) === "instance") {
        return data;
    }
    this._ = Ul.clone(data);
    this.enny = options.enny;
};

Enny.Instance.prototype.connect = function (ins, options, callback) {

    var self = this;
    if (typeof options === "boolean") {
        options = {
            client: options
        };
    } else if (options === "function") {
        callback = options;
        options = {};
    }

    callback = callback || function (err) {
        if (err) { console.error(err); }
    };
    options = Ul.merge(options, {
        client: true
    });
    ins = Enny.Instance(ins, options);

    if (!ins._.name) {
        return callback(new Error("The target instance name is required."));
    }

    if (!self._.name) {
        return callback(new Error("The source instance name is required."));
    }

    var load = null;
    if (options.client) {
        self._.client = Deffy(self._.client, {});
        load = self._.client.load = Deffy(self._.client.load, []);
    } else {
        load = self._.load = Deffy(self._.load, []);
    }
    load.push(ins._.name);
    if (options.save) {
        self.enny.save(callback);
        return self;
    }
    callback();
    return self;
};

Enny.Instance.prototype.addFlow = function (flElm, options, callback) {

    var self = this;
    if (typeof options === "boolean") {
        options = {
            client: options
        };
    } else if (options === "function") {
        callback = options;
        options = {};
    }

    callback = callback || function (err) {
        if (err) { console.error(err); }
    };

    options = Ul.merge(options, {
        client: true
    });

    var flow = null;
    if (options.client) {
        self._.client = Deffy(self._.client, {});
        flow = self._.client.flow = Deffy(self._.client.flow, []);
    } else {
        flow = self._.flow = Deffy(self._.flow, []);
    }

    flElm = new Enny.FlowElement(flElm);

    flow.push(flElm);

    if (options.save) {
        self.enny.save(callback);
        return self;
    }

    callback();
};

Enny.FlowElement = function FlowElement (data) {
    var self = this;
    if (Typpy(data) === "flowelement") {
        return data;
    }
    this._ = [];
    if (Typpy(data) === "array") {
        data.forEach(self.addComponent.bind(self));
    }
};

Enny.FlowElement.prototype.toJSON = function () {
    return this._.map(function (c) {
        return c.toFlow();
    });
};

Enny.FlowElement.prototype.addComponent = function (data) {
    data = new Enny.FlowComponent(data);
    this._.push(data);
};

Enny.FlowElement.prototype.toFlow = function () {
    return this._.map(function (c) {
        return c.toFlow();
    });
};

Enny.Handler = function Handler(data) {
    if (Typpy(data) === "handler") {
        return data;
    }
    this.to = data.to;
    this.args = Deffy(data.args, []);
    this.isStream = Deffy(data.isStream, true);
    this.handler = data.handler;
};

Enny.Handler.prototype.toFlow = function () {
    var res = [];
    res[0] = (this.isStream ? "" : ":") + (this.to ? this.to + "/" : "") + this.handler;
    if (!this.args.length) {
        return res[0];
    }
    res = res.concat(this.args);
    return res;
};

Enny.FlowComponent = function FlowComponent (data) {
    var self = this;
    if (Typpy(data) === "flowcomponent") {
        return data;
    }
    if (data.event) {
        data.type = TYPES.event;
    }
    self.data = Ul.clone(data);
};

Enny.FlowComponent.prototype.toFlow = function () {
    var data = this.data;
    var res = null;
    switch (data.type) {
        case TYPES.event:
            if (data.once) {
                return [data.event];
            }
            return data.event;
        case TYPES.dataHandler:
        case TYPES.streamHandler:
            return new Enny.Handler({
                to: data.to,
                isStream: data.type === TYPES.streamHandler,
                args: data.args,
                handler: data.handler
            }).toFlow();
        case TYPES.load:
            return new Enny.Handler({
                args: [[data.instance]],
                handler: TYPES.load
            }).toFlow();
    }
};

// instance/method
// !instance/method
// >instance/method
// :instance/method
// method
Enny.parseMethod = function (input, defaultIns) {
    var output = {
        instance: defaultIns
    };
    switch (input.charAt(0)) {
        case "!":
            output.type = TYPES.errorHandler;
            input = input.substr(1);
            break;
        case ":":
            output.type = TYPES.dataHandler;
            input = input.substr(1);
            break;
        case ">":
            output.disableInput = true;
            input = input.substr(1);
            break;
        default:
            break;
    }
    var splits = input.split("/");
    if (splits.length === 2) {
        output.instance = splits[0];
        output.method = splits[1];
    } else {
        output.method = splits[0];
    }
    return output;
}

Enny.parseFlow = function (_input, instName) {

    var input = Ul.clone(_input);
    var output = {
        events: {},
        _events: {}
    };

    for (var i = 0; i < input.length; ++i) {
        var comp = input[i];
        var type = Typpy(comp[0])
        if (type !== "string") {
            continue;
        }
        var eventName = comp[0];
        var ev = output._events[eventName] = output._events[eventName] || [];
        ev.push(comp);
        comp.shift();
    }

    var evs = Object.keys(output._events);
    for (var i = 0; i < evs.length; ++i) {
        var cEvent = evs[i];
        var cFlow = output._events[cEvent];
        var cEv = output.events[cEvent] = [];
        for (var ii = 0; ii < cFlow.length; ++ii) {
            var cFlowElement = cFlow[ii];
            var pFlowElement = [];
            for (var iii = 0; iii < cFlowElement.length; ++iii) {
                var cComponent = cFlowElement[iii];
                if (Typpy(cComponent, String)) {
                    cComponent = [cComponent];
                }
                var cElm = {};
                switch (cComponent[0]) {
                    case TYPES.load:
                        cElm.type = TYPES.load;
                        cElm.args = cComponent.slice(1);
                    case TYPES.emit:
                        cElm.type = TYPES.emit;
                        cElm.args = cComponent.slice(1).map(function (c) {
                            return Enny.parseMethod(c, instName);
                        });
                        break;
                }

                if (!cElm.type) {
                    cElm = Enny.parseMethod(cComponent[0]);
                    cElm.args = cComponent.slice(1);
                    cElm.type = TYPES.streamHandler;
                }
                pFlowElement.push(cElm);
            }

            cEv.push(pFlowElement);
        }
    }

    var out = [];
    Object.keys(output.events).forEach(function (c) {
        out.push({
            on: c,
            _: output.events[c]
        });
    });

    return out;
};

Enny.TYPES = TYPES;

module.exports = Enny;
<commit_msg>Parse the instance flow<commit_after>var Ul = require("ul");
var Typpy = require("typpy");
var Deffy = require("deffy");
var IterateObject = require("iterate-object")

const TYPES = {
    // :some/datahandler
    dataHandler: "dataHandler",
    // !some/error-handelr
    errorHandler: "errorHandler",
    // instance/method
    streamHandler: "streamHandler",
    // load
    // TODO
    load: "load",
    // ["instance/emit", "some-event"]
    emit: "emit",
    // ["link", "instance/method"]
    link: "link",
    // "event"
    listener: "listener"
};

function Enny() {
    var self = this;
    self.instances = {};
    self.Instance = function (data) {
        return new Enny.Instance(data, {
            enny: self
        });
    };
    self.FlowComponent = function (data) {
        return new Enny.FlowComponent(data, {
            enny: self
        });
    };
}

Enny.prototype.toJSON = function (a, b, c) {
    var self = this;
    var obj = {};
    Object.keys(self.instances).forEach(function (name) {
        obj[name] = self.instances[name]._;
    });
    return obj;
};

Enny.prototype.addInstance = function (ins) {
    ins = this.Instance(ins);
    this.instances[ins._.name] = ins;
    return ins;
};

Enny.Instance = function Instance (data, options) {
    if (Typpy(data) === "instance") {
        return data;
    }
    this._ = Ul.clone(data);
    this.enny = options.enny;
};

Enny.Instance.prototype.connect = function (ins, options, callback) {

    var self = this;
    if (typeof options === "boolean") {
        options = {
            client: options
        };
    } else if (options === "function") {
        callback = options;
        options = {};
    }

    callback = callback || function (err) {
        if (err) { console.error(err); }
    };
    options = Ul.merge(options, {
        client: true
    });
    ins = Enny.Instance(ins, options);

    if (!ins._.name) {
        return callback(new Error("The target instance name is required."));
    }

    if (!self._.name) {
        return callback(new Error("The source instance name is required."));
    }

    var load = null;
    if (options.client) {
        self._.client = Deffy(self._.client, {});
        load = self._.client.load = Deffy(self._.client.load, []);
    } else {
        load = self._.load = Deffy(self._.load, []);
    }
    load.push(ins._.name);
    if (options.save) {
        self.enny.save(callback);
        return self;
    }
    callback();
    return self;
};

Enny.Instance.prototype.addFlow = function (flElm, options, callback) {

    var self = this;
    if (typeof options === "boolean") {
        options = {
            client: options
        };
    } else if (options === "function") {
        callback = options;
        options = {};
    }

    callback = callback || function (err) {
        if (err) { console.error(err); }
    };

    options = Ul.merge(options, {
        client: true
    });

    var flow = null;
    if (options.client) {
        self._.client = Deffy(self._.client, {});
        flow = self._.client.flow = Deffy(self._.client.flow, []);
    } else {
        flow = self._.flow = Deffy(self._.flow, []);
    }

    flElm = new Enny.FlowElement(flElm);

    flow.push(flElm);

    if (options.save) {
        self.enny.save(callback);
        return self;
    }

    callback();
};

Enny.FlowElement = function FlowElement (data) {
    var self = this;
    if (Typpy(data) === "flowelement") {
        return data;
    }
    this._ = [];
    if (Typpy(data) === "array") {
        data.forEach(self.addComponent.bind(self));
    }
};

Enny.FlowElement.prototype.toJSON = function () {
    return this._.map(function (c) {
        return c.toFlow();
    });
};

Enny.FlowElement.prototype.addComponent = function (data) {
    data = new Enny.FlowComponent(data);
    this._.push(data);
};

Enny.FlowElement.prototype.toFlow = function () {
    return this._.map(function (c) {
        return c.toFlow();
    });
};

Enny.Handler = function Handler(data) {
    if (Typpy(data) === "handler") {
        return data;
    }
    this.to = data.to;
    this.args = Deffy(data.args, []);
    this.isStream = Deffy(data.isStream, true);
    this.handler = data.handler;
};

Enny.Handler.prototype.toFlow = function () {
    var res = [];
    res[0] = (this.isStream ? "" : ":") + (this.to ? this.to + "/" : "") + this.handler;
    if (!this.args.length) {
        return res[0];
    }
    res = res.concat(this.args);
    return res;
};

Enny.FlowComponent = function FlowComponent (data) {
    var self = this;
    if (Typpy(data) === "flowcomponent") {
        return data;
    }
    if (data.event) {
        data.type = TYPES.listener;
    }
    self.data = Ul.clone(data);
};

Enny.FlowComponent.prototype.toFlow = function () {
    var data = this.data;
    var res = null;
    switch (data.type) {
        case TYPES.listener:
            if (data.once) {
                return [data.event];
            }
            return data.event;
        case TYPES.dataHandler:
        case TYPES.streamHandler:
            return new Enny.Handler({
                to: data.to,
                isStream: data.type === TYPES.streamHandler,
                args: data.args,
                handler: data.handler
            }).toFlow();
        case TYPES.load:
            return new Enny.Handler({
                args: [[data.instance]],
                handler: TYPES.load
            }).toFlow();
    }
};

// instance/method
// !instance/method
// >instance/method
// :instance/method
// method
Enny.parseMethod = function (input, defaultIns) {
    var output = {
        instance: defaultIns,
        type: TYPES.streamHandler
    };
    switch (input.charAt(0)) {
        case "!":
            output.type = TYPES.errorHandler;
            input = input.substr(1);
            break;
        case ":":
            output.type = TYPES.dataHandler;
            input = input.substr(1);
            break;
        case ">":
            output.disableInput = true;
            input = input.substr(1);
            break;
        default:
            break;
    }
    var splits = input.split("/");
    if (splits.length === 2) {
        output.instance = splits[0];
        output.method = splits[1];
    } else {
        output.method = splits[0];
    }
    return output;
}

Enny.parseFlowComponent = function (_input, instName) {
    var input = Ul.clone(_input);

    if (Typpy(input, String)) {
        input = [input];
    }

    var output = {};
    // Load
    if (input[0] === TYPES.load) {
        output.type = TYPES.load;
        output.args = input.slice(1);
    // Emit
    } else if (Enny.parseMethod(input[0]).method === "emit") {
        output.type = TYPES.emit;
        output.args = input.slice(1).map(function (c) {
            return Enny.parseMethod(c, instName);
        });
    }

    // Stream handler
    if (!output.type) {
        output = Enny.parseMethod(input[0], instName);
        output.args = input.slice(1);
    }

    return output;
};

Enny.instanceFlow = function (_input, name) {
    var output = {
        // TODO
        load: {},

        dataHandler: {},
        errorHandler: {},
        streamHandler: {},
        emit: {},
        listener: {}
    };

    if (!_input.length) {
        return output;
    }

    IterateObject(_input, function (i, f) {
        // Collect listeners
        output.listener[f[0]] = {
            event: f[0],
            type: TYPES.listener
        };
        IterateObject(f.slice(1), function (ii, c) {
            c = Enny.parseFlowComponent(c, name);
            if (c.instance !== name) { return; }
            output[c.type][c.method] = c;
        });
    });
    return output;
};

Enny.parseFlow = function (_input, instName) {

    var input = Ul.clone(_input);
    var output = {
        // TODO
        loads: {},
        dataHandlers: {},
        errorHandlers: {},
        streamHandlers: {},
        emits: {},
        listeners: {}
    };

    for (var i = 0; i < input.length; ++i) {
        var comp = input[i];
        var type = Typpy(comp[0])
        if (type !== "string") {
            continue;
        }
        var eventName = comp[0];
        var ev = output._events[eventName] = output._events[eventName] || [];
        ev.push(comp);
        comp.shift();
    }

    var evs = Object.keys(output._events);
    for (var i = 0; i < evs.length; ++i) {
        var cEvent = evs[i];
        var cFlow = output._events[cEvent];
        var cEv = output.events[cEvent] = [];
        for (var ii = 0; ii < cFlow.length; ++ii) {
            var cFlowElement = cFlow[ii];
            var pFlowElement = [];
            for (var iii = 0; iii < cFlowElement.length; ++iii) {
                var cComponent = cFlowElement[iii];
                if (Typpy(cComponent, String)) {
                    cComponent = [cComponent];
                }
                var cElm = {};
                if (cComponent[0] === TYPES.load) {
                    cElm.type = TYPES.load;
                    cElm.args = cComponent.slice(1);
                } else if (Enny.parseMethod(cComponent[0]).method === "emit") {
                    cElm.type = TYPES.emit;
                    cElm.args = cComponent.slice(1).map(function (c) {
                        return Enny.parseMethod(c, instName);
                    });
                }

                if (!cElm.type) {
                    cElm = Enny.parseMethod(cComponent[0], instName);
                    cElm.args = cComponent.slice(1);
                    cElm.type = TYPES.streamHandler;
                }

                pFlowElement.push(cElm);
            }

            cEv.push(pFlowElement);
        }
    }

    var out = [];
    Object.keys(output.events).forEach(function (c) {
        out.push({
            on: c,
            _: output.events[c]
        });
    });

    return out;
};

Enny.TYPES = TYPES;

module.exports = Enny;
<|endoftext|>


<commit_before>import _ from 'lodash';

/*
 * Cable is a messaging utility with tree and graph message broadcasting combining the centricity of mediators with the semantic protections of signal-slot.
 *
 * @module adaptiveui-cable
 * @license
 * adaptiveui-cable 1.0.0 <https://adaptiveui.io/>
 * Copyright 2016 Adaptive UI <https://adaptiveui.io/>
 * Available under MIT license <https://adaptiveui.io/license>
 */
// TODO add preventPropagation()
export default function Cable(options) {

  if (!(this instanceof Cable)) {
    return new Cable(options);
  }

  this.publish = function(channelName) {
    return this.walkPublish(channelName);
  };

  this.subscribe = function(channelName) {
    return this.walkSubscribe(channelName);
  };

  this.__id__ = _.uniqueId();
  this.__channels__ = {};
  this.options = _.merge({
    asynchronous: true
  }, options);

  this.options.invocation = (!!this.options.asynchronous)
    ? 'defer'
    : 'attempt';
};

var findGroupingCharacter = function findGroupingCharacter(channelName) {
  return _.reduce(['.', '/', ':', '-'], function getGroupingCharacter(splitCharacter, character) {
    return splitCharacter + ((channelName.indexOf(character) >= 0)
        ? character
        : '');
  }, '')
};

var calculateParentSet = function calculateParentSet(channelName) {
  const splitCharacter = findGroupingCharacter(channelName);
  return (splitCharacter === '')
    ? [channelName]
    : channelName.split(splitCharacter);
};

Cable.singleReceiptFn = (function(value) {

});

Cable.prototype = {

  bridge(localChannel, bridgeToChannel) {

    localChannel = (_.isString(localChannel))
      ? this.walkChannel(localChannel)
      : localChannel;

    // TODO check if it is a function or error
    bridgeToChannel = (_.isString(bridgeToChannel))
      ? this.walkPublish(bridgeToChannel)
      : bridgeToChannel;

    localChannel.__bridges__.push(bridgeToChannel);
    return this;
  },

  /*
   *
   */
  channel(channelName) {

    const cable = this;
    const channelNames = calculateParentSet(channelName);

    var parents = [];

    _.each(channelNames, function(name) {
      cable.shallowChannel(name, parents);
      parents.push(name);
    });

    return this;
  },

  /*
   * one.twoC.threeA, []
   * one.twoC.threeA, ['one']
   * one.twoC.threeA, ['one', 'twoC']
   */
  shallowChannel(channelName, parents) {

    const cable = this;
    const uniquePath = this.__id__ + '--' + parents.join('-') + '-' + channelName;
    const parentList = (parents || []);
    const childrenAllExist = this.childrenAllExist(this.__channels__, parentList);
    const alreadyExists = !childrenAllExist;

    if (alreadyExists) {
      return;
    }

    const channels = this.walkParents(this.__channels__, parentList);
    const subscriber = this.walkParents(this.subscribe, parentList);
    const publisher = this.walkParents(this.publish, parentList);

    channels[channelName] = channels[channelName] || {
        __slots__: [],
        __bridges__: []
      };

    publisher[channelName] = publisher[channelName] || function(...params) {

        const receiptFn = (!_.isFunction(publisher[channelName].receipt.receiptFn))
          ? Cable.singleReceiptFn
          : publisher[channelName].receipt.receiptFn;

        params.unshift(receiptFn);

        Cable.__graph__ = {};

        _[cable.options.invocation](function() {
          publisher[channelName]._helper.apply(cable, params);
          publisher[channelName].receipt.receiptFn = undefined;
        });

        return publisher;
      };

    publisher[channelName]._helper = publisher[channelName]._helper || function(receiptFn, ...params) {

        if (Cable.__graph__[uniquePath]) {
          return;
        }

        Cable.__graph__[uniquePath] = true;

        // TODO break up list into 100 call packets so we do not slow down rendering
        _.each(channels[channelName].__slots__, function(subscriber) {
          receiptFn(subscriber.method.apply(subscriber.host, params));
        });

        params.unshift(receiptFn);

        // FIXME what about cross calls on a broadcast?
        _.each(channels[channelName].__bridges__, function(bridge, key) {
          bridge._helper.apply(bridge, params);
        });

        return publisher;
      };

    publisher[channelName].receipt = publisher[channelName].receipt || function(fn) {
        publisher[channelName].receipt.receiptFn = fn;
        return publisher[channelName];
      };

    publisher[channelName].broadcast = publisher[channelName].broadcast || function(...params) {

        const receiptFn = (!_.isFunction(publisher[channelName].receipt.receiptFn))
          ? Cable.singleReceiptFn
          : publisher[channelName].receipt.receiptFn;

        params.unshift(receiptFn);

        Cable.__graph__ = {};

        _[cable.options.invocation](function() {
          publisher[channelName].broadcast._helper.apply(cable, params);
          publisher[channelName].receipt.receiptFn = undefined;
        });

        return publisher;
      };

    publisher[channelName].broadcast._helper = publisher[channelName].broadcast._helper || function(receiptFn, ...params) {

        if (Cable.__graph__[uniquePath]) {
          return;
        }

        Cable.__graph__[uniquePath] = true;

        _.each(channels[channelName].__slots__, function(subscriber) {
          receiptFn(subscriber.method.apply(subscriber.host, params));
        });

        params.unshift(receiptFn);

        _.each(publisher[channelName], function(childChannel, name) {
          if (_.isFunction(childChannel.broadcast) && name !== 'broadcast') {
            childChannel.broadcast._helper.apply(childChannel, params);
          }
        });

        _.each(channels[channelName].__bridges__, function(bridge, key) {
          bridge.broadcast._helper.apply(bridge, params);
        });

        return publisher;
      };

    subscriber[channelName] = subscriber[channelName] || function(host, method) {

        const isSlot = !_.isUndefined(method);

        method = (isSlot)
          ? method
          : host;

        // TODO what does a function type default to?
        host = (isSlot)
          ? host
          : {};

        if (isSlot && _.isString(method)) {
          method = host[method];
        }

        channels[channelName].__slots__.push({
          host: host,
          method: method
        });

        return subscriber;
      };

    return this;
  },

  childrenAllExist(tree, descentRule) {

    const n = descentRule.length;
    var root = tree;
    var i = 0;

    while (!!descentRule[i] && !!root[descentRule[i]]) {
      root = root[descentRule[i]];
      i += 1;
    }

    return i === n;
  },

  walkChannel(channelName) {
    return this.walkParents(this.__channels__, calculateParentSet(channelName));
  },

  walkPublish(channelName) {
    return this.walkParents(this.publish, calculateParentSet(channelName));
  },

  walkSubscribe(channelName) {
    return this.walkParents(this.subscribe, calculateParentSet(channelName));
  },

  walkParents(tree, descentRule) {
    return (_.size(descentRule) > 0)
      ? this.walkParents(tree[_.head(descentRule)], _.tail(descentRule))
      : tree;
  },

  /*
   * @return {String} source of cable
   */
  toString() {
    return '';
  }

};
<commit_msg>CableNode exists<commit_after>import _ from 'lodash';

var __GRAPH__ = {};

export class CableNode {

  /**
   *
   */
  constructor(uniquePath, options) {

    this.uniquePath = uniquePath;
    this.id = _.uniqueId();
    this.__channels__ = [];   // children
    this.__slots__ = [];      // functions
    this.__bridges__ = [];    // bridgers to other Cables

    this.options = options;
    this.options.invocation = 'attempt';
  }

  addChannel(channelName) {
    const cableNode = CableNode(this.uniquePath + '.' + channelName, this.options);
    this.__channels__.push(cableNode);
    return cableNode;
  }

  publish(...params) {

    //const receiptFn = (!_.isFunction(publisher[channelName].receipt.receiptFn))
    //  ? Cable.singleReceiptFn
    //  : publisher[channelName].receipt.receiptFn;
    //
    params.unshift(function() {
    });

    __GRAPH__[this.id] = {};

    _[cable.options.invocation](function() {
      _publish.apply(cable, params);
      //publisher[channelName].receipt.receiptFn = undefined;
    });

    return this;
  }

  _publish(receiptFn, ...params) {

    if (__GRAPH__[this.id][this.uniquePath]) {
      return;
    }

    __GRAPH__[this.id][this.uniquePath] = true;

    // TODO break up list into 100 call packets so we do not slow down rendering
    _.each(this.__slots__, (subscriber) => {
      receiptFn(subscriber.method.apply(subscriber.host, params));
    });

    params.unshift(receiptFn);

    // FIXME what about cross calls on a broadcast?
    _.each(this.__bridges__, (bridge, key) => {
      bridge._helper.apply(bridge, params);
    });

    return this;
  }

  receipt(fn) {
    this.receiptFn = fn;
    return this;
  }

  broadcast(...params) {
    //const receiptFn = (!_.isFunction(publisher[channelName].receipt.receiptFn))
    //  ? Cable.singleReceiptFn
    //  : publisher[channelName].receipt.receiptFn;
    //
    //params.unshift(receiptFn);
    params.unshift(function() {
    });

    __GRAPH__[this.id] = {};

    _[this.options.invocation](() => {
      this._broadcast.apply(this, params);
      this.receiptFn = undefined;
    });

    return this;
  }

  _broadcast(receiptFn, ...params) {
    if (__GRAPH__[this.id][this.uniquePath]) {
      return;
    }

    __GRAPH__[this.id][this.uniquePath] = true;

    _.each(this.__slots__, (subscriber) => {
      receiptFn(subscriber.method.apply(subscriber.host, params));
    });

    params.unshift(receiptFn);

    // TODO loop over channels
    _.each(this.__channels__, (childChannel) => {
      childChannel._broadcast.apply(childChannel, params);
    });

    _.each(this.__bridges__, (bridge, key) => {
      bridge._broadcast.apply(bridge, params);
    });

    return this;
  }

  subscribe(host, method) {

    const isSlot = !_.isUndefined(method);

    method = (isSlot)
      ? method
      : host;

    // TODO what does a function type default to?
    host = (isSlot)
      ? host
      : {};

    if (isSlot && _.isString(method)) {
      method = host[method];
    }

    this.__slots__.push({
      host,
      method
    });

    return this;
  }
}

/*
 * Cable is a messaging utility with tree and graph message broadcasting combining the centricity of mediators with the semantic protections of signal-slot.
 *
 * @module adaptiveui-cable
 * @license
 * adaptiveui-cable 1.0.0 <https://adaptiveui.io/>
 * Copyright 2016 Adaptive UI <https://adaptiveui.io/>
 * Available under MIT license <https://adaptiveui.io/license>
 */
// TODO add preventPropagation()
export default function Cable(options) {

  if (!(this instanceof Cable)) {
    return new Cable(options);
  }

  this.publish = function(channelName) {
    return this.walkPublish(channelName);
  };

  this.subscribe = function(channelName) {
    return this.walkSubscribe(channelName);
  };

  this.__id__ = _.uniqueId();
  this.__channels__ = {};
  this.options = _.merge({
    asynchronous: true
  }, options);

  this.options.invocation = (!!this.options.asynchronous)
    ? 'defer'
    : 'attempt';
};

var findGroupingCharacter = function findGroupingCharacter(channelName) {
  return _.reduce(['.', '/', ':', '-'], function getGroupingCharacter(splitCharacter, character) {
    return splitCharacter + ((channelName.indexOf(character) >= 0)
        ? character
        : '');
  }, '')
};

var calculateParentSet = function calculateParentSet(channelName) {
  const splitCharacter = findGroupingCharacter(channelName);
  return (splitCharacter === '')
    ? [channelName]
    : channelName.split(splitCharacter);
};

Cable.singleReceiptFn = (function(value) {

});

Cable.prototype = {

  bridge(localChannel, bridgeToChannel) {

    localChannel = (_.isString(localChannel))
      ? this.walkChannel(localChannel)
      : localChannel;

    // TODO check if it is a function or error
    bridgeToChannel = (_.isString(bridgeToChannel))
      ? this.walkPublish(bridgeToChannel)
      : bridgeToChannel;

    localChannel.__bridges__.push(bridgeToChannel);
    return this;
  },

  /*
   *
   */
  channel(channelName) {

    const cable = this;
    const channelNames = calculateParentSet(channelName);

    var parents = [];

    _.each(channelNames, function(name) {
      cable.shallowChannel(name, parents);
      parents.push(name);
    });

    return this;
  },

  /*
   * one.twoC.threeA, []
   * one.twoC.threeA, ['one']
   * one.twoC.threeA, ['one', 'twoC']
   */
  shallowChannel(channelName, parents) {

    const cable = this;
    const uniquePath = this.__id__ + '--' + parents.join('-') + '-' + channelName;
    const parentList = (parents || []);
    const childrenAllExist = this.childrenAllExist(this.__channels__, parentList);
    const alreadyExists = !childrenAllExist;

    if (alreadyExists) {
      return;
    }

    const channels = this.walkParents(this.__channels__, parentList);
    const subscriber = this.walkParents(this.subscribe, parentList);
    const publisher = this.walkParents(this.publish, parentList);

    channels[channelName] = channels[channelName] || {
        __slots__: [],
        __bridges__: []
      };

    publisher[channelName] = publisher[channelName] || function(...params) {

        const receiptFn = (!_.isFunction(publisher[channelName].receipt.receiptFn))
          ? Cable.singleReceiptFn
          : publisher[channelName].receipt.receiptFn;

        params.unshift(receiptFn);

        Cable.__graph__ = {};

        _[cable.options.invocation](function() {
          publisher[channelName]._helper.apply(cable, params);
          publisher[channelName].receipt.receiptFn = undefined;
        });

        return publisher;
      };

    publisher[channelName]._helper = publisher[channelName]._helper || function(receiptFn, ...params) {

        if (Cable.__graph__[uniquePath]) {
          return;
        }

        Cable.__graph__[uniquePath] = true;

        // TODO break up list into 100 call packets so we do not slow down rendering
        _.each(channels[channelName].__slots__, function(subscriber) {
          receiptFn(subscriber.method.apply(subscriber.host, params));
        });

        params.unshift(receiptFn);

        // FIXME what about cross calls on a broadcast?
        _.each(channels[channelName].__bridges__, function(bridge, key) {
          bridge._helper.apply(bridge, params);
        });

        return publisher;
      };

    publisher[channelName].receipt = publisher[channelName].receipt || function(fn) {
        publisher[channelName].receipt.receiptFn = fn;
        return publisher[channelName];
      };

    publisher[channelName].broadcast = publisher[channelName].broadcast || function(...params) {

        const receiptFn = (!_.isFunction(publisher[channelName].receipt.receiptFn))
          ? Cable.singleReceiptFn
          : publisher[channelName].receipt.receiptFn;

        params.unshift(receiptFn);

        Cable.__graph__ = {};

        _[cable.options.invocation](function() {
          publisher[channelName].broadcast._helper.apply(cable, params);
          publisher[channelName].receipt.receiptFn = undefined;
        });

        return publisher;
      };

    publisher[channelName].broadcast._helper = publisher[channelName].broadcast._helper || function(receiptFn,
                                                                                ...params) {

        if (Cable.__graph__[uniquePath]) {
          return;
        }

        Cable.__graph__[uniquePath] = true;

        _.each(channels[channelName].__slots__, function(subscriber) {
          receiptFn(subscriber.method.apply(subscriber.host, params));
        });

        params.unshift(receiptFn);

        _.each(publisher[channelName], function(childChannel, name) {
          if (_.isFunction(childChannel.broadcast) && name !== 'broadcast') {
            childChannel.broadcast._helper.apply(childChannel, params);
          }
        });

        _.each(channels[channelName].__bridges__, function(bridge, key) {
          bridge.broadcast._helper.apply(bridge, params);
        });

        return publisher;
      };

    subscriber[channelName] = subscriber[channelName] || function(host, method) {

        const isSlot = !_.isUndefined(method);

        method = (isSlot)
          ? method
          : host;

        // TODO what does a function type default to?
        host = (isSlot)
          ? host
          : {};

        if (isSlot && _.isString(method)) {
          method = host[method];
        }

        channels[channelName].__slots__.push({
          host: host,
          method: method
        });

        return subscriber;
      };

    return this;
  },

  childrenAllExist(tree, descentRule) {

    const n = descentRule.length;
    var root = tree;
    var i = 0;

    while (!!descentRule[i] && !!root[descentRule[i]]) {
      root = root[descentRule[i]];
      i += 1;
    }

    return i === n;
  },

  walkChannel(channelName) {
    return this.walkParents(this.__channels__, calculateParentSet(channelName));
  },

  walkPublish(channelName) {
    return this.walkParents(this.publish, calculateParentSet(channelName));
  },

  walkSubscribe(channelName) {
    return this.walkParents(this.subscribe, calculateParentSet(channelName));
  },

  walkParents(tree, descentRule) {
    return (_.size(descentRule) > 0)
      ? this.walkParents(tree[_.head(descentRule)], _.tail(descentRule))
      : tree;
  },

  /*
   * @return {String} source of cable
   */
  toString() {
    return '';
  }

};
<|endoftext|>


<commit_before>var express     = require('express')
  , Promise     = require('bluebird')
  , bodyParser  = require('body-parser')
  , winston     = require('winston')
  , config      = require('config')
  , _           = require('lodash')
  , crypto      = require('crypto')
  , express_jwt = require('express-jwt')
  // todo [akamel] remove this module
  , auth_header = require('auth-header')
  , mongoose    = require('mongoose')
  , morgan      = require('morgan')
  , ipfilter    = require('express-ipfilter').IpFilter
  //
  , mongodb     = require('./api/mongodb')
  , docusign    = require('./api/docusign')
  , secret      = require('./api/secret')
  , auth        = require('./auth/index')
  //
  , User        = require('./model/User')
  , Credential  = require('./model/Credential')
  , Repository  = require('./model/Repository')
  , Mongo       = require('./model/backend/Mongo')
  ;

mongoose.connect(config.getUrl('mongo'));

var app = express();

app.use(bodyParser.json());

app.use(morgan('dev'));

var auth_middleware = express_jwt({
    secret          : config.get('jwt.public')
  // , getToken  : (req) => req.body.token
  , algorithm       : 'RS256'
  , requestProperty : 'jwt_payload'
});

var ipfilter_middleware = _.size(config.get('account.ip-whitelist'))
                            ? ipfilter(config.get('account.ip-whitelist'), { mode : 'allow', allowedHeaders : ['x-forwarded-for'] })
                            : (req, res, next) => next();

app.get('/mongodb/creds', auth_middleware, mongodb.creds)
app.get('/docusign/creds', auth_middleware, docusign.creds)

// todo [akamel] protect ? already protected by token in path?
app.get('/account/:id/secret/:key/token', secret.token);
app.put('/account/:id/secret/', ipfilter_middleware, secret.create);
app.delete('/account/:id/secret/:hash', ipfilter_middleware, secret.del);

app.use(auth.passport.initialize());
app.use(auth.passport.session());
app.get('/auth/logout', auth.logout);
app.get('/auth/:provider', auth.login);
app.get('/auth/:provider/callback', auth.callback);

app.get('/account', auth_middleware, (req, res, next) => {
  let _id = req.jwt_payload.sub;

  User
    .findById(_id)
    .exec()
    .then((account) => {
      res.send({ data : account.sanitize() });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:id/git_token', auth_middleware, (req, res, next) => {
  let _id = req.jwt_payload.sub
    , id  = req.params['id']
    ;

  Promise
    .try(() => {
      if (_id != id) {
        throw new Error('id mismatch');
      }

      return User.findOne({ _id }).exec();
    })
    .then((account) => {
      let rdns = User.reverseDNS(provider);

      res.send({ data : { token : _.get(account, `accounts.${rdns}._token`) } });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:id/token/', ipfilter_middleware, (req, res, next) => {
  var id = req.params['id'];

  User
    .findById(id)
    .exec()
    .then((account) => {
      if (!account) {
        throw new Error('not found');
      }

      return account
              .issueJWT({ expiresIn : req.body.expiresIn })
              .then((token) => {
                res.send({ data : token });
              });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:provider/:id/token', ipfilter_middleware, (req, res, next) => {
  var provider    = req.params['provider']
    , id          = req.params['id']
    , rdns        = User.reverseDNS(provider)
    , query       = {
          provider
        , [`accounts.${rdns}.username`] : id
      }
    ;

  User
    .findOne(query)
    .exec()
    .then((account) => {
      if (!account) {
        throw new Error('not found');
      }

      return account
              .issueJWT({ expiresIn : req.body.expiresIn })
              .then((token) => {
                res.send({ data : token });
              });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:provider/:id/git_token', ipfilter_middleware, (req, res, next) => {
  var provider    = req.params['provider']
    , id          = req.params['id']
    , rdns        = User.reverseDNS(provider)
    , query       = {
          provider
        , [`accounts.${rdns}.username`] : id
      }
    ;

  Promise
    .try(() => {
      return User.findOne(query).exec();
    })
    .then((account) => {
      let rdns = User.reverseDNS(provider);

      res.send({ data : { token : _.get(account, `accounts.${rdns}._token`) } });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:_id/', ipfilter_middleware, (req, res, next) => {
  var _id = req.params['_id'];

  User
    .findById(_id)
    .exec()
    .then((account) => {
      res.send({ data : account.sanitize() });
    })
    .catch((err) => {
      next(err);
    });
});

app.use(function(err, req, res, next) {
  switch (err.message) {
    case 'not found':
    res.status(404);
    break;
    default:
    res.status(500);
  }

  if (err.name === 'UnauthorizedError') {
    res.status(401);
    err.message = 'unauthorized';
  }

  res.send({ message : err.message });
});

function listen(options, cb) {
  return Promise
          .promisify(app.listen, { context : app})(options.port)
          .nodeify(cb);
}

module.exports = {
    listen : listen
};<commit_msg>take expires_in<commit_after>var express     = require('express')
  , Promise     = require('bluebird')
  , bodyParser  = require('body-parser')
  , winston     = require('winston')
  , config      = require('config')
  , _           = require('lodash')
  , crypto      = require('crypto')
  , express_jwt = require('express-jwt')
  // todo [akamel] remove this module
  , auth_header = require('auth-header')
  , mongoose    = require('mongoose')
  , morgan      = require('morgan')
  , ipfilter    = require('express-ipfilter').IpFilter
  //
  , mongodb     = require('./api/mongodb')
  , docusign    = require('./api/docusign')
  , secret      = require('./api/secret')
  , auth        = require('./auth/index')
  //
  , User        = require('./model/User')
  , Credential  = require('./model/Credential')
  , Repository  = require('./model/Repository')
  , Mongo       = require('./model/backend/Mongo')
  ;

mongoose.connect(config.getUrl('mongo'));

var app = express();

app.use(bodyParser.json());

app.use(morgan('dev'));

var auth_middleware = express_jwt({
    secret          : config.get('jwt.public')
  // , getToken  : (req) => req.body.token
  , algorithm       : 'RS256'
  , requestProperty : 'jwt_payload'
});

var ipfilter_middleware = _.size(config.get('account.ip-whitelist'))
                            ? ipfilter(config.get('account.ip-whitelist'), { mode : 'allow', allowedHeaders : ['x-forwarded-for'] })
                            : (req, res, next) => next();

app.get('/mongodb/creds', auth_middleware, mongodb.creds)
app.get('/docusign/creds', auth_middleware, docusign.creds)

// todo [akamel] protect ? already protected by token in path?
app.get('/account/:id/secret/:key/token', secret.token);
app.put('/account/:id/secret/', ipfilter_middleware, secret.create);
app.delete('/account/:id/secret/:hash', ipfilter_middleware, secret.del);

app.use(auth.passport.initialize());
app.use(auth.passport.session());
app.get('/auth/logout', auth.logout);
app.get('/auth/:provider', auth.login);
app.get('/auth/:provider/callback', auth.callback);

app.get('/account', auth_middleware, (req, res, next) => {
  let _id = req.jwt_payload.sub;

  User
    .findById(_id)
    .exec()
    .then((account) => {
      res.send({ data : account.sanitize() });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:id/git_token', auth_middleware, (req, res, next) => {
  let _id = req.jwt_payload.sub
    , id  = req.params['id']
    ;

  Promise
    .try(() => {
      if (_id != id) {
        throw new Error('id mismatch');
      }

      return User.findOne({ _id }).exec();
    })
    .then((account) => {
      let rdns = User.reverseDNS(provider);

      res.send({ data : { token : _.get(account, `accounts.${rdns}._token`) } });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:id/token/', ipfilter_middleware, (req, res, next) => {
  var { id }          = req.params
    , { expires_in }  = req.query
    ;

  User
    .findById(id)
    .exec()
    .then((account) => {
      if (!account) {
        throw new Error('not found');
      }

      return account
              .issueJWT({ expiresIn : expires_in })
              .then((token) => {
                res.send({ data : token });
              });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:provider/:id/token', ipfilter_middleware, (req, res, next) => {
  var { id, provider }  = req.params
    , { expires_in }    = req.query
    , rdns              = User.reverseDNS(provider)
    , query             = {
          provider
        , [`accounts.${rdns}.username`] : id
      }
    ;

  User
    .findOne(query)
    .exec()
    .then((account) => {
      if (!account) {
        throw new Error('not found');
      }

      return account
              .issueJWT({ expiresIn : expires_in })
              .then((token) => {
                res.send({ data : token });
              });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:provider/:id/git_token', ipfilter_middleware, (req, res, next) => {
  var provider    = req.params['provider']
    , id          = req.params['id']
    , rdns        = User.reverseDNS(provider)
    , query       = {
          provider
        , [`accounts.${rdns}.username`] : id
      }
    ;

  Promise
    .try(() => {
      return User.findOne(query).exec();
    })
    .then((account) => {
      let rdns = User.reverseDNS(provider);

      res.send({ data : { token : _.get(account, `accounts.${rdns}._token`) } });
    })
    .catch((err) => {
      next(err);
    });
});

app.get('/account/:_id/', ipfilter_middleware, (req, res, next) => {
  var _id = req.params['_id'];

  User
    .findById(_id)
    .exec()
    .then((account) => {
      res.send({ data : account.sanitize() });
    })
    .catch((err) => {
      next(err);
    });
});

app.use(function(err, req, res, next) {
  switch (err.message) {
    case 'not found':
    res.status(404);
    break;
    default:
    res.status(500);
  }

  if (err.name === 'UnauthorizedError') {
    res.status(401);
    err.message = 'unauthorized';
  }

  res.send({ message : err.message });
});

function listen(options, cb) {
  return Promise
          .promisify(app.listen, { context : app})(options.port)
          .nodeify(cb);
}

module.exports = {
    listen : listen
};<|endoftext|>


<commit_before>'use strict';

const precompile = require('@glimmer/compiler').precompile;
const Minimatch = require('minimatch').Minimatch;
const getConfig = require('./get-config');
const stripBom = require('strip-bom');
const chalk = require('chalk');

const TransformDotComponentInvocation = require('./plugins/transform-dot-component-invocation');

const WARNING_SEVERITY = 1;
const ERROR_SEVERITY = 2;

class Linter {
  constructor(_options) {
    let options = _options || {};

    this.options = options;
    this.console = options.console || console;

    this.loadConfig();
    this.constructor = Linter;
  }

  loadConfig() {
    this.config = getConfig(this.options);
  }

  _defaultSeverityForRule(ruleName, pendingStatus) {
    if (typeof pendingStatus === 'boolean') {
      return pendingStatus ? WARNING_SEVERITY : ERROR_SEVERITY;
    } else if (pendingStatus.only){
      if (pendingStatus.only.indexOf(ruleName) > -1) {
        return WARNING_SEVERITY;
      } else {
        return ERROR_SEVERITY;
      }
    }

    return 2;
  }

  buildASTPlugins(config) {
    let results = config.results;

    function addToResults(result) {
      results.push(result);
    }

    let rules = this.config.loadedRules;
    let astPlugins = [TransformDotComponentInvocation];

    for (let pluginName in rules) {

      let Plugin = rules[pluginName];
      let plugin = new Plugin({
        name: pluginName,
        config: this.config.rules[pluginName],
        console: this.console,
        log: addToResults,
        defaultSeverity: this._defaultSeverityForRule(pluginName, config.pending)
      });

      astPlugins.push(env => {
        plugin.templateEnvironmentData = env;

        let visitor = plugin.getVisitor();

        return {
          name: pluginName,
          visitor
        };
      });
    }

    return astPlugins;
  }

  statusForModule(type, moduleId) {
    let list = this.config[type];
    if (!list) { return false; }

    for (let i = 0; i < list.length; i++) {
      let item = list[i];

      if (item instanceof Minimatch && item.match(moduleId)) {
        return true;
      } else if (typeof item === 'string' && moduleId === item) {
        return true;
      } else if (item.moduleId === moduleId){
        return item;
      }
    }

    return false;
  }

  verify(options) {
    let messages = [];
    let pendingStatus = this.statusForModule('pending', options.moduleId);
    let shouldIgnore = this.statusForModule('ignore', options.moduleId);

    if (shouldIgnore) {
      return messages;
    }

    let pluginConfig = {
      results: messages,
      pending: pendingStatus
    };

    try {
      precompile(stripBom(options.source), {
        moduleName: options.moduleId,
        rawSource: stripBom(options.source),
        plugins: {
          ast: this.buildASTPlugins(pluginConfig)
        }
      });
    } catch (error) {
      messages.push({
        fatal: true,
        moduleId: options.moduleId,
        message: error.message,
        source: error.stack,
        severity: 2
      });
    }

    if (pendingStatus && messages.length === 0) {
      messages.push({
        message: `Pending module (\`${options.moduleId}\`) passes all rules. Please remove \`${options.moduleId}\` from pending list.`,
        moduleId: options.moduleId,
        severity: 2
      });
    }

    return messages;
  }

  logLintingError(name, moduleName, message) {
    this._messages.push({
      rule: name,
      moduleId: moduleName,
      message
    });

    this.console.log(message);
  }

  static errorsToMessages(filePath, errors, options) {
    errors = errors || [];
    options = options || {
      verbose: false
    };

    if (errors.length === 0) {
      return '';
    }

    let errorsMessages = errors.map((error) => this._formatError(error, options)).join('\n');

    return `${chalk.underline(filePath)}\n${errorsMessages}\n`;
  }

  static _formatError(error, options) {
    let message = '';
    let severities = {
      1: 'warrning',
      2: 'error'
    };

    if (error.line && error.column) {
      message += chalk.dim(`  ${error.line}:${error.column}`);
    } else {
      message += chalk.dim('  -:-');
    }

    message += `  ${chalk.red(severities[error.severity] || 'error')}`;
    message += `  ${error.message}  ${chalk.dim(error.rule)}`;

    if (options.verbose) {
      message += `\n${error.source}`;
    }

    return message;
  }
}

module.exports = Linter;
module.exports.Rule = require('./rules/base');
module.exports.ASTHelpers = require('./helpers/ast-node-info');
<commit_msg>colorize error severity<commit_after>'use strict';

const precompile = require('@glimmer/compiler').precompile;
const Minimatch = require('minimatch').Minimatch;
const getConfig = require('./get-config');
const stripBom = require('strip-bom');
const chalk = require('chalk');

const TransformDotComponentInvocation = require('./plugins/transform-dot-component-invocation');

const WARNING_SEVERITY = 1;
const ERROR_SEVERITY = 2;

class Linter {
  constructor(_options) {
    let options = _options || {};

    this.options = options;
    this.console = options.console || console;

    this.loadConfig();
    this.constructor = Linter;
  }

  loadConfig() {
    this.config = getConfig(this.options);
  }

  _defaultSeverityForRule(ruleName, pendingStatus) {
    if (typeof pendingStatus === 'boolean') {
      return pendingStatus ? WARNING_SEVERITY : ERROR_SEVERITY;
    } else if (pendingStatus.only){
      if (pendingStatus.only.indexOf(ruleName) > -1) {
        return WARNING_SEVERITY;
      } else {
        return ERROR_SEVERITY;
      }
    }

    return 2;
  }

  buildASTPlugins(config) {
    let results = config.results;

    function addToResults(result) {
      results.push(result);
    }

    let rules = this.config.loadedRules;
    let astPlugins = [TransformDotComponentInvocation];

    for (let pluginName in rules) {

      let Plugin = rules[pluginName];
      let plugin = new Plugin({
        name: pluginName,
        config: this.config.rules[pluginName],
        console: this.console,
        log: addToResults,
        defaultSeverity: this._defaultSeverityForRule(pluginName, config.pending)
      });

      astPlugins.push(env => {
        plugin.templateEnvironmentData = env;

        let visitor = plugin.getVisitor();

        return {
          name: pluginName,
          visitor
        };
      });
    }

    return astPlugins;
  }

  statusForModule(type, moduleId) {
    let list = this.config[type];
    if (!list) { return false; }

    for (let i = 0; i < list.length; i++) {
      let item = list[i];

      if (item instanceof Minimatch && item.match(moduleId)) {
        return true;
      } else if (typeof item === 'string' && moduleId === item) {
        return true;
      } else if (item.moduleId === moduleId){
        return item;
      }
    }

    return false;
  }

  verify(options) {
    let messages = [];
    let pendingStatus = this.statusForModule('pending', options.moduleId);
    let shouldIgnore = this.statusForModule('ignore', options.moduleId);

    if (shouldIgnore) {
      return messages;
    }

    let pluginConfig = {
      results: messages,
      pending: pendingStatus
    };

    try {
      precompile(stripBom(options.source), {
        moduleName: options.moduleId,
        rawSource: stripBom(options.source),
        plugins: {
          ast: this.buildASTPlugins(pluginConfig)
        }
      });
    } catch (error) {
      messages.push({
        fatal: true,
        moduleId: options.moduleId,
        message: error.message,
        source: error.stack,
        severity: 2
      });
    }

    if (pendingStatus && messages.length === 0) {
      messages.push({
        message: `Pending module (\`${options.moduleId}\`) passes all rules. Please remove \`${options.moduleId}\` from pending list.`,
        moduleId: options.moduleId,
        severity: 2
      });
    }

    return messages;
  }

  logLintingError(name, moduleName, message) {
    this._messages.push({
      rule: name,
      moduleId: moduleName,
      message
    });

    this.console.log(message);
  }

  static errorsToMessages(filePath, errors, options) {
    errors = errors || [];
    options = options || {
      verbose: false
    };

    if (errors.length === 0) {
      return '';
    }

    let errorsMessages = errors.map((error) => this._formatError(error, options)).join('\n');

    return `${chalk.underline(filePath)}\n${errorsMessages}\n`;
  }

  static _formatError(error, options) {
    let message = '';

    if (error.line && error.column) {
      message += chalk.dim(`  ${error.line}:${error.column}`);
    } else {
      message += chalk.dim('  -:-');
    }

    if (error.severity === WARNING_SEVERITY) {
      message += `  ${chalk.yellow('warning')}`;
    } else {
      message += `  ${chalk.red('error')}`;
    }

    message += `  ${error.message}  ${chalk.dim(error.rule)}`;

    if (options.verbose) {
      message += `\n${error.source}`;
    }

    return message;
  }
}

module.exports = Linter;
module.exports.Rule = require('./rules/base');
module.exports.ASTHelpers = require('./helpers/ast-node-info');
<|endoftext|>


<commit_before>// Dependencies
var Lien = require("lien")
  , Tinyreq = require("tinyreq")
  , Ul = require("ul")
  ;

/*!
 * Wrabbit
 * Creates a new `Wrabbit` instance.
 *
 * @name Wrabbit
 * @function
 */
function Wrabbit() {}

/**
 * req
 * Creates a request to the provided url.
 *
 * @name req
 * @function
 * @param {String} url The script url.
 * @param {Function} callback The callback function.
 * @return {Request} The request object.
 */
Wrabbit.prototype.req = function (url, callback) {
    if (!url) { return callback("Missing the file to wrap", 400); }
    return Tinyreq(url, function (err, content, res) {
        if (err) { return callback(err, 500); }
        if (res.statusCode === 404) { return callback("The provided url ends with 404.", 404); }
        if (res.statusCode !== 200) { return callback("Cannot access the provided file.", 400); }
        callback(null, content);
    });
};

/**
 * wrap
 * Wrap content with the wrapping code.
 *
 * @name wrap
 * @function
 * @param {String} content The content to wrap.
 * @param {String} wrapline The wrapping line (which will be prepended to the content).
 * @return {String} The wrapped content.
 */
Wrabbit.prototype.wrap = function (content, wrapline) {
    return wrapline + "\n" + content + "\nreturn module;});";
};

/**
 * wrapUrl
 * Wraps the content of a script by providing its url.
 *
 * @name wrapUrl
 * @function
 * @param {String} url The script url.
 * @param {String} wrapline The wrapping line (which will be prepended to the content).
 * @param {Function} callback The callback function.
 */
Wrabbit.prototype.wrapUrl = function (url, wrapline, callback) {
    var self = this;
    self.req(url, function (err, content) {
        if (err) { return callback(err, content); }
        callback(null, self.wrap(content, wrapline));
    });
};

/**
 * server
 * Starts the `Wrabbit` server.
 *
 * @name server
 * @function
 * @param {Object|Number} options The `Lien` server options or the server port.
 * @param {Function} callback The callback function called after the server is started.
 */
Wrabbit.prototype.server = function (options, callback) {

    var self = this;

    if (typeof options === "number") {
        options = {
            port: options
          , host: null
        };
    }

    options = Ul.merge(options, {
        host: "localhost"
      , root: __dirname + "/public"
    });

    var server = new Lien(options);

    server.page.add("/api", function (lien) {
        self.wrapUrl(lien.search.url, "E('http://" + lien.req.headers["host"] + lien.req.url + "', function (require, module, exports, global, engine) {", function (err, res) {
            if (err) { return lien.end(err, res); }
            lien.end(res, 200, "js");
        });
    });

    server.page.add("/", "html/index.html");
    server.on("load", callback);
};

module.exports = new Wrabbit();
<commit_msg>Allow cros site requests<commit_after>// Dependencies
var Lien = require("lien")
  , Tinyreq = require("tinyreq")
  , Ul = require("ul")
  ;

/*!
 * Wrabbit
 * Creates a new `Wrabbit` instance.
 *
 * @name Wrabbit
 * @function
 */
function Wrabbit() {}

/**
 * req
 * Creates a request to the provided url.
 *
 * @name req
 * @function
 * @param {String} url The script url.
 * @param {Function} callback The callback function.
 * @return {Request} The request object.
 */
Wrabbit.prototype.req = function (url, callback) {
    if (!url) { return callback("Missing the file to wrap", 400); }
    return Tinyreq(url, function (err, content, res) {
        if (err) { return callback(err, 500); }
        if (res.statusCode === 404) { return callback("The provided url ends with 404.", 404); }
        if (res.statusCode !== 200) { return callback("Cannot access the provided file.", 400); }
        callback(null, content);
    });
};

/**
 * wrap
 * Wrap content with the wrapping code.
 *
 * @name wrap
 * @function
 * @param {String} content The content to wrap.
 * @param {String} wrapline The wrapping line (which will be prepended to the content).
 * @return {String} The wrapped content.
 */
Wrabbit.prototype.wrap = function (content, wrapline) {
    return wrapline + "\n" + content + "\nreturn module;});";
};

/**
 * wrapUrl
 * Wraps the content of a script by providing its url.
 *
 * @name wrapUrl
 * @function
 * @param {String} url The script url.
 * @param {String} wrapline The wrapping line (which will be prepended to the content).
 * @param {Function} callback The callback function.
 */
Wrabbit.prototype.wrapUrl = function (url, wrapline, callback) {
    var self = this;
    self.req(url, function (err, content) {
        if (err) { return callback(err, content); }
        callback(null, self.wrap(content, wrapline));
    });
};

/**
 * server
 * Starts the `Wrabbit` server.
 *
 * @name server
 * @function
 * @param {Object|Number} options The `Lien` server options or the server port.
 * @param {Function} callback The callback function called after the server is started.
 */
Wrabbit.prototype.server = function (options, callback) {

    var self = this;

    if (typeof options === "number") {
        options = {
            port: options
          , host: null
        };
    }

    options = Ul.merge(options, {
        host: "localhost"
      , root: __dirname + "/public"
    });

    var server = new Lien(options);

    server.page.add("/api", function (lien) {
        self.wrapUrl(lien.search.url, "E('http://" + lien.req.headers["host"] + lien.req.url + "', function (require, module, exports, global, engine) {", function (err, res) {
            if (err) { return lien.end(err, res); }
            lien.end(res, 200, "js", {
                "Access-Control-Allow-Origin": "*"
            });
        });
    });

    server.page.add("/", "html/index.html");
    server.on("load", callback);
};

module.exports = new Wrabbit();
<|endoftext|>


<commit_before>"use strict";

var CityTour = CityTour || {};

CityTour.NeighborhoodGenerator = (function() {
  var MIN_DISTANCE_BETWEEN_NEIGHBORHOODS = 10;

  // The size of the square that is used to calculate the terrain flatness
  // around a given point. Each value should be an odd number.
  var NEIGHBORHOOD_CENTER_WIDTH = 9;
  var NEIGHBORHOOD_CENTER_DEPTH = 9;
  var FLATNESS_WINDOW_WIDTH_MARGIN = (NEIGHBORHOOD_CENTER_WIDTH - 1) / 2;
  var FLATNESS_WINDOW_DEPTH_MARGIN = (NEIGHBORHOOD_CENTER_DEPTH - 1) / 2;

  var calculateFlatnessScores = function(terrain) {
    var flatnessScores = [];
    var x, z;

    var minX = terrain.minMapX() + FLATNESS_WINDOW_WIDTH_MARGIN;
    var maxX = terrain.maxMapX() - FLATNESS_WINDOW_WIDTH_MARGIN;
    var minZ = terrain.minMapZ() + FLATNESS_WINDOW_DEPTH_MARGIN;
    var maxZ = terrain.maxMapZ() - FLATNESS_WINDOW_DEPTH_MARGIN;

    for (x = minX; x <= maxX; x++) {
      flatnessScores[x] = [];

      for (z = minZ; z <= maxZ; z++) {
        if (terrain.waterHeightAtCoordinates(x, z) > 0.0) {
          flatnessScores[x][z] = Number.POSITIVE_INFINITY;
        }
        else {
          flatnessScores[x][z] = averageHeightDifferenceAroundPoint(terrain, x, z);
        }
      }
    }

    return flatnessScores;
  };

  var averageHeightDifferenceAroundPoint = function(terrain, centerX, centerZ) {
    var centerHeight = terrain.landHeightAtCoordinates(centerX, centerZ);
    var pointCount = 0;
    var totalHeightDeltas = 0.0;
    var minX = Math.max(terrain.minMapX(), centerX - FLATNESS_WINDOW_WIDTH_MARGIN);
    var maxX = Math.min(terrain.maxMapX(), centerX + FLATNESS_WINDOW_WIDTH_MARGIN);
    var minZ = Math.max(terrain.minMapZ(), centerZ - FLATNESS_WINDOW_DEPTH_MARGIN);
    var maxZ = Math.min(terrain.maxMapZ(), centerZ + FLATNESS_WINDOW_DEPTH_MARGIN);
    var x, z;

    for (x = minX; x <= maxX; x++) {
      for (z = minZ; z <= maxZ; z++) {
        totalHeightDeltas += Math.abs(centerHeight - terrain.landHeightAtCoordinates(x, z));
        pointCount += 1;
      }
    }

    return totalHeightDeltas / pointCount;
  };

  var closestNeighborhoodDistance = function(neighborhoods, x, z) {
    var minDistanceToNeighborhood = Number.POSITIVE_INFINITY;
    var distanceToClosestNeighborhood;
    var i;

    if (neighborhoods.length === 0) {
      return 0;
    }

    for (i = 0; i < neighborhoods.length; i++) {
      distanceToClosestNeighborhood = CityTour.Math.distanceBetweenPoints(x, z, neighborhoods[i].centerX, neighborhoods[i].centerZ);
      if (distanceToClosestNeighborhood < minDistanceToNeighborhood) {
        minDistanceToNeighborhood = distanceToClosestNeighborhood;
      }
    }

    return minDistanceToNeighborhood;
  };

  var bestNeighborhoodSite = function(terrain, flatnessScores, neighborhoods) {
    var bestSiteCoordinates = { x: terrain.minMapX(), z: terrain.minMapZ() };
    var bestSiteScore = Number.POSITIVE_INFINITY;
    var score, centralityScore, flatnessScore;
    var distanceToClosestNeighborhood;
    var x, z;

    var minX = terrain.minMapX() + FLATNESS_WINDOW_WIDTH_MARGIN;
    var maxX = terrain.maxMapX() - FLATNESS_WINDOW_WIDTH_MARGIN;
    var minZ = terrain.minMapZ() + FLATNESS_WINDOW_DEPTH_MARGIN;
    var maxZ = terrain.maxMapZ() - FLATNESS_WINDOW_DEPTH_MARGIN;

    for (x = minX; x < maxX; x++) {
      for (z = minZ; z < maxZ; z++) {
        centralityScore = Math.abs(x) + Math.abs(z);

        flatnessScore = flatnessScores[x][z];

        distanceToClosestNeighborhood = closestNeighborhoodDistance(neighborhoods, x, z);
        if (distanceToClosestNeighborhood < MIN_DISTANCE_BETWEEN_NEIGHBORHOODS) {
          distanceToClosestNeighborhood = 1000;
        }

        score = centralityScore + (flatnessScore * 10) + distanceToClosestNeighborhood;

        if (score < bestSiteScore) {
          bestSiteScore = score;
          bestSiteCoordinates.x = x;
          bestSiteCoordinates.z = z;
        }
      }
    }

    return bestSiteCoordinates;
  };

  var generate = function(terrain, count) {
    var flatnessScores = calculateFlatnessScores(terrain);
    var neighborhoods = [];
    var neighborhoodCenter;
    var i;

    for (i = 0; i < count; i++) {
      neighborhoodCenter = bestNeighborhoodSite(terrain, flatnessScores, neighborhoods);
      neighborhoods.push({ centerX: neighborhoodCenter.x, centerZ: neighborhoodCenter.z });
    }

    return neighborhoods;
  };

  return {
    generate: generate,
  };
})();
<commit_msg>Avoiding repeated calculations of neighborhood centrality scores<commit_after>"use strict";

var CityTour = CityTour || {};

CityTour.NeighborhoodGenerator = (function() {
  var MIN_DISTANCE_BETWEEN_NEIGHBORHOODS = 10;

  // The size of the square that is used to calculate the terrain flatness
  // around a given point. Each value should be an odd number.
  var NEIGHBORHOOD_CENTER_WIDTH = 9;
  var NEIGHBORHOOD_CENTER_DEPTH = 9;
  var FLATNESS_WINDOW_WIDTH_MARGIN = (NEIGHBORHOOD_CENTER_WIDTH - 1) / 2;
  var FLATNESS_WINDOW_DEPTH_MARGIN = (NEIGHBORHOOD_CENTER_DEPTH - 1) / 2;

  var calculateScores = function(terrain) {
    var scores = [];
    var score;
    var x, z;

    var minX = terrain.minMapX() + FLATNESS_WINDOW_WIDTH_MARGIN;
    var maxX = terrain.maxMapX() - FLATNESS_WINDOW_WIDTH_MARGIN;
    var minZ = terrain.minMapZ() + FLATNESS_WINDOW_DEPTH_MARGIN;
    var maxZ = terrain.maxMapZ() - FLATNESS_WINDOW_DEPTH_MARGIN;

    for (x = minX; x <= maxX; x++) {
      scores[x] = [];

      for (z = minZ; z <= maxZ; z++) {
        score = { flatness: Number.POSITIVE_INFINITY, centrality: Math.abs(x) + Math.abs(z) };
        if (terrain.waterHeightAtCoordinates(x, z) === 0.0) {
          score.flatness = averageHeightDifferenceAroundPoint(terrain, x, z);
        }

        scores[x][z] = score;
      }
    }

    return scores;
  };

  var averageHeightDifferenceAroundPoint = function(terrain, centerX, centerZ) {
    var centerHeight = terrain.landHeightAtCoordinates(centerX, centerZ);
    var pointCount = 0;
    var totalHeightDeltas = 0.0;
    var minX = Math.max(terrain.minMapX(), centerX - FLATNESS_WINDOW_WIDTH_MARGIN);
    var maxX = Math.min(terrain.maxMapX(), centerX + FLATNESS_WINDOW_WIDTH_MARGIN);
    var minZ = Math.max(terrain.minMapZ(), centerZ - FLATNESS_WINDOW_DEPTH_MARGIN);
    var maxZ = Math.min(terrain.maxMapZ(), centerZ + FLATNESS_WINDOW_DEPTH_MARGIN);
    var x, z;

    for (x = minX; x <= maxX; x++) {
      for (z = minZ; z <= maxZ; z++) {
        totalHeightDeltas += Math.abs(centerHeight - terrain.landHeightAtCoordinates(x, z));
        pointCount += 1;
      }
    }

    return totalHeightDeltas / pointCount;
  };

  var closestNeighborhoodDistance = function(neighborhoods, x, z) {
    var minDistanceToNeighborhood = Number.POSITIVE_INFINITY;
    var distanceToClosestNeighborhood;
    var i;

    if (neighborhoods.length === 0) {
      return 0;
    }

    for (i = 0; i < neighborhoods.length; i++) {
      distanceToClosestNeighborhood = CityTour.Math.distanceBetweenPoints(x, z, neighborhoods[i].centerX, neighborhoods[i].centerZ);
      if (distanceToClosestNeighborhood < minDistanceToNeighborhood) {
        minDistanceToNeighborhood = distanceToClosestNeighborhood;
      }
    }

    return minDistanceToNeighborhood;
  };

  var bestNeighborhoodSite = function(terrain, scores, neighborhoods) {
    var bestSiteCoordinates = { x: terrain.minMapX(), z: terrain.minMapZ() };
    var bestSiteScore = Number.POSITIVE_INFINITY;
    var score, scoreComponents;
    var distanceToClosestNeighborhood;
    var x, z;

    var minX = terrain.minMapX() + FLATNESS_WINDOW_WIDTH_MARGIN;
    var maxX = terrain.maxMapX() - FLATNESS_WINDOW_WIDTH_MARGIN;
    var minZ = terrain.minMapZ() + FLATNESS_WINDOW_DEPTH_MARGIN;
    var maxZ = terrain.maxMapZ() - FLATNESS_WINDOW_DEPTH_MARGIN;

    for (x = minX; x < maxX; x++) {
      for (z = minZ; z < maxZ; z++) {
        scoreComponents = scores[x][z];

        distanceToClosestNeighborhood = closestNeighborhoodDistance(neighborhoods, x, z);
        if (distanceToClosestNeighborhood < MIN_DISTANCE_BETWEEN_NEIGHBORHOODS) {
          distanceToClosestNeighborhood = 1000;
        }

        score = scoreComponents.centrality + (scoreComponents.flatness * 10) + distanceToClosestNeighborhood;

        if (score < bestSiteScore) {
          bestSiteScore = score;
          bestSiteCoordinates.x = x;
          bestSiteCoordinates.z = z;
        }
      }
    }

    return bestSiteCoordinates;
  };

  var generate = function(terrain, count) {
    var scores = calculateScores(terrain);
    var neighborhoods = [];
    var neighborhoodCenter;
    var i;

    for (i = 0; i < count; i++) {
      neighborhoodCenter = bestNeighborhoodSite(terrain, scores, neighborhoods);
      neighborhoods.push({ centerX: neighborhoodCenter.x, centerZ: neighborhoodCenter.z });
    }

    return neighborhoods;
  };

  return {
    generate: generate,
  };
})();
<|endoftext|>


<commit_before>var restify = require('restify');
var bunyan = require('bunyan');
var q = require('q');
var debug = require('debug')('bravado:server');
var path = require('path');
var inflection = require('inflection');
var package = require('../package.json');
var config = require('./config');
var bravado = require('bravado-core');
var cors = require('./cors');
var routeHandler = require('./route');
var indexRouteHandler = require('./index-route');
var schemasRouteHandler = require('./schemas-route');

var server = undefined;

module.exports = {

  start: function (api, options) {
    debug('starting server');
    if (options) {
      config.load(options);
      config.validate({strict: true});
    }

    var serverOptions = {
      name: config.get('name'),
      version: package.version
    };

    server = restify.createServer(serverOptions);
    server.use(restify.queryParser({ mapParams: false }));
    server.use(restify.gzipResponse());
    server.use(restify.bodyParser({
      mapParams: false,
      mapFiles: false
    }));

    // load api definitions
    var loadPromise;
    if ('string' === typeof api) {
      loadPromise = bravado.ApiDefinition.load(api);
    } else if (Array.isArray(api)) {
      loadPromise = q.all(api.map(function (item) {
        return bravado.ApiDefinition.load(api);
      }));
    }

    return loadPromise
      .then(function (defs) {
        var routes = {};
        debug('api definition loaded: %j', api);
        if (!Array.isArray(defs)) {
          defs = [defs];
        }
        defs.forEach(function (def) {
          def.validate();
          var resourcePath = path.resolve(path.dirname(def['x-bravado-sourceFile']), config.get('path'));
          for (var r in def.resources) {
            var resource = def.resources[r];
            var controllerPath = path.resolve(resourcePath, resource['x-bravado-controller']);
            for (var a in resource.actions) {
              var action = resource.actions[a];
              var method = action.method.toLowerCase();
              if (method === 'delete') { method = 'del'; }
              if (method === 'options') { method = 'opts'; }
              var fullPath = action['x-bravado-fullPath'];
              var routePath = fullPath.replace(/\{((?:[\w.~-]|(?:%[0-9A-F]{2}))+)\}/g, ':$1');
              if (!routes[routePath]) {
                routes[routePath] = [];
              }
              routes[routePath].push({
                name: [r, a].join('.'),
                method: method,
                handler: routeHandler(def, r, a, require(controllerPath))
              });
            }
          }
          routes[def.basePath] = [{
            name: 'index',
            method: 'get',
            handler: indexRouteHandler(def)
          }];
          routes[def.basePath + 'schemas'] = [{
            name: 'schemas',
            method: 'get',
            handler: schemasRouteHandler(def)
          }];
        });
        Object.keys(routes).sort().reverse().forEach(function (routePath) {
          routes[routePath].forEach(function (route) {
            debug('routing %s for %s', routePath, route.name);
            server.opts(routePath, cors.preflight());
            server[route.method](routePath, cors.headers(), route.handler);
          });
        });
        return q.resolve();
      })
      .then(function () {
        var logger = restify.auditLogger({
          log: bunyan.createLogger({
            name: 'audit',
            stream: process.stdout
          })
        });
        server.on('after', function (req, res, route, err) {
          logger(req, res, route, err);
        });
        server.on('NotFound', function (req, res, err, cb) {
          res.send(404, { type: 'NotFound', message: err.message });
          cb();
        });
        server.on('MethodNotAllowed', function (req, res, err, cb) {
          res.send(405, { type: 'MethodNotAllowed', message: err.message });
          cb();
        });
        server.on('InternalServer', function (req, res, err, cb) {
          res.send(500, { type: 'ServerError', message: err.message });
          cb();
        });
        server.on('uncaughtException', function (req, res, route, err) {
          logger(req, res, route, err);
          res.send(err.statusCode || 500, { type: err.type || 'Error', message: err.message });
        });

        server.listen(
          config.get('port'),
          config.get('host'),
          function () {
            debug('%s listening at %s', server.name, server.url);
          }
        );
      }).catch(function (err) {
        console.log(err.stack);
      });
  },

  stop: function () {
    debug('stopping server');
    server.close();
  }

};
<commit_msg>adds route versioning<commit_after>var restify = require('restify');
var bunyan = require('bunyan');
var q = require('q');
var debug = require('debug')('bravado:server');
var path = require('path');
var inflection = require('inflection');
var package = require('../package.json');
var config = require('./config');
var bravado = require('bravado-core');
var cors = require('./cors');
var routeHandler = require('./route');
var indexRouteHandler = require('./index-route');
var schemasRouteHandler = require('./schemas-route');

var server = undefined;

module.exports = {

  start: function (api, options) {
    debug('starting server');
    if (options) {
      config.load(options);
      config.validate({strict: true});
    }

    var serverOptions = {
      name: config.get('name'),
      version: package.version
    };

    server = restify.createServer(serverOptions);
    server.use(restify.queryParser({ mapParams: false }));
    server.use(restify.gzipResponse());
    server.use(restify.bodyParser({
      mapParams: false,
      mapFiles: false
    }));

    // load api definitions
    var loadPromise;
    if ('string' === typeof api) {
      loadPromise = bravado.ApiDefinition.load(api);
    } else if (Array.isArray(api)) {
      loadPromise = q.all(api.map(function (item) {
        return bravado.ApiDefinition.load(item);
      }));
    }

    return loadPromise
      .then(function (defs) {
        var routes = {};
        debug('api definition loaded: %j', api);
        if (!Array.isArray(defs)) {
          defs = [defs];
        }
        defs.forEach(function (def) {
          def.validate();
          var resourcePath = path.resolve(path.dirname(def['x-bravado-sourceFile']), config.get('path'));
          for (var r in def.resources) {
            var resource = def.resources[r];
            var controllerPath = path.resolve(resourcePath, resource['x-bravado-controller']);
            for (var a in resource.actions) {
              var action = resource.actions[a];
              var method = action.method.toLowerCase();
              if (method === 'delete') { method = 'del'; }
              if (method === 'options') { method = 'opts'; }
              var fullPath = action['x-bravado-fullPath'];
              var routePath = fullPath.replace(/\{((?:[\w.~-]|(?:%[0-9A-F]{2}))+)\}/g, ':$1');
              if (!routes[routePath]) {
                routes[routePath] = [];
              }
              routes[routePath].push({
                name: [r, a].join('.'),
                method: method,
                version: def.info.version,
                handler: routeHandler(def, r, a, require(controllerPath))
              });
            }
          }
          routes[def.basePath] = [{
            name: 'index',
            method: 'get',
            version: def.info.version,
            handler: indexRouteHandler(def)
          }];
          routes[def.basePath + 'schemas'] = [{
            name: 'schemas',
            method: 'get',
            version: def.info.version,
            handler: schemasRouteHandler(def)
          }];
        });
        Object.keys(routes).sort().reverse().forEach(function (routePath) {
          routes[routePath].forEach(function (route) {
            debug('routing %s@%s for %s', routePath, route.version, route.name);
            server.opts(routePath, cors.preflight());
            server[route.method](
              { path: routePath, version: route.version },
              cors.headers(),
              route.handler
            );
          });
        });
        return q.resolve();
      })
      .then(function () {
        var logger = restify.auditLogger({
          log: bunyan.createLogger({
            name: 'audit',
            stream: process.stdout
          })
        });
        server.on('after', function (req, res, route, err) {
          logger(req, res, route, err);
        });
        server.on('NotFound', function (req, res, err, cb) {
          res.send(404, { type: 'NotFound', message: err.message });
          cb();
        });
        server.on('MethodNotAllowed', function (req, res, err, cb) {
          res.send(405, { type: 'MethodNotAllowed', message: err.message });
          cb();
        });
        server.on('VersionNotAllowed', function (req, res, err, cb) {
          res.send(400, { type: 'VersionNotAllowed', message: err.message });
          cb();
        });
        server.on('InternalServer', function (req, res, err, cb) {
          res.send(500, { type: 'ServerError', message: err.message });
          cb();
        });
        server.on('uncaughtException', function (req, res, route, err) {
          logger(req, res, route, err);
          res.send(err.statusCode || 500, { type: err.type || 'Error', message: err.message });
        });

        server.listen(
          config.get('port'),
          config.get('host'),
          function () {
            debug('%s listening at %s', server.name, server.url);
          }
        );
      }).catch(function (err) {
        console.log(err.stack);
      });
  },

  stop: function () {
    debug('stopping server');
    server.close();
  }

};
<|endoftext|>


<commit_before>module.exports = {
  temperature: require("./temperature"),
  torque: require("./torque"),
  types: require("./types")
};
<commit_msg>forgot to add it to the library<commit_after>module.exports = {
  dailyProduction: require("./daily-production"),
  temperature: require("./temperature"),
  torque: require("./torque"),
  types: require("./types"),
};
<|endoftext|>