<commit_before>(function(root) {

    var PREFIXES = 'webkit moz o ms'.split(' ');

    // Base object for different progress bar shapes

    var Progress = function(container, opts) {
        // Prevent calling constructor without parameters so inheritance
        // works correctly
        if (arguments.length === 0) return;

        var svgView = this._createSvgView(opts);
        var element = isString(container)
            ? document.querySelector(container)
            : container;

        element.appendChild(svgView.svg);

        this._path = new Path(svgView.path, opts);
    };

    Progress.prototype.animate = function animate(percent, opts, cb) {
        this._path.stop();
        this._path.animate(percent, opts, cb);
    };

    Progress.prototype.stop = function stop() {
        this._path.stop();
    };

    Progress.prototype.set = function set(percent) {
        this._path.set(percent);
    };

    Progress.prototype._createSvgView = function _createSvgView(opts) {
        opts = extend({
            color: "#555",
            strokeWidth: 1.0,
            trailColor: "#f4f4f4",
            fill: null
        }, opts);

        var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        svg.setAttribute("viewBox", "0 0 100 100");

        if (opts.trailColor) {
            var trailOpts = extend({}, opts);
            trailOpts.color = opts.trailColor;
            var trailPath = this._createPath(trailOpts);
            svg.appendChild(trailPath);
        }

        var path = this._createPath(opts);
        svg.appendChild(path);

        return {
            svg: svg,
            path: path
        }
    };

    Progress.prototype._createPath = function _createPath(opts) {
        var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
        path.setAttributeNS(null, "d", this._pathString(opts));
        path.setAttributeNS(null, "stroke", opts.color);
        path.setAttributeNS(null, "stroke-width", opts.strokeWidth);

        if (opts.fill) {
            path.setAttributeNS(null, "fill", opts.fill);
        } else {
            path.setAttributeNS(null, "fill-opacity", "0");
        }

        return path;
    };

    Progress.prototype._pathString = function _pathString(opts) {
        throw new Error("Override this function for each progress bar");
    };

    // Progress bar shapes

    var Circle = function(container, options) {
        Progress.apply(this, arguments);
    };

    Circle.prototype = new Progress();
    Circle.prototype.constructor = Circle;

    Circle.prototype._pathString = function _pathString(opts) {
        // Use two arcs to form a circle
        // See this answer http://stackoverflow.com/a/10477334/1446092
        var pathString = "M 50,50 m 0,-{r} a {r},{r} 0 1 1 0,{r*2} a {r},{r} 0 1 1 0,-{r*2}";
        var r = 50 - opts.strokeWidth / 2;
        pathString = pathString.replace(/\{r\}/g, r);
        pathString = pathString.replace(/\{r\*2\}/g, r * 2);
        return pathString;
    };

    var Square = function(container, options) {
        Progress.apply(this, arguments);
    };

    Square.prototype = new Progress();
    Square.prototype.constructor = Square;

    Square.prototype._pathString = function _pathString(opts) {
        var pathString = "M 0,{s/2} L {w},{s/2} L {w},{w} L {s/2},{w} L {s/2},{s}";
        var w = 100 - opts.strokeWidth / 2;
        pathString = pathString.replace(/\{w\}/g, w);
        pathString = pathString.replace(/\{s\}/g, opts.strokeWidth);
        pathString = pathString.replace(/\{s\/2\}/g, opts.strokeWidth / 2);
        return pathString;
    };

    // Lower level API to animate any kind of svg path

    var Path = function(path, opts) {
        opts = extend({
            duration: 800,
            easing: "ease-in-out"
        }, opts);

        this._path = path;
        this._opts = opts;
        this._callbacks = {};

        // Set up the starting positions
        var length = this._path.getTotalLength();
        this._path.style.strokeDasharray = length + ' ' + length;
        this._path.style.strokeDashoffset = length;
    };

    Path.prototype.set = function set(percent) {
        this._setTransition('none');

        var length = this._path.getTotalLength();
        this._path.style.strokeDashoffset = length - (percent / 100) * length;
    };

    Path.prototype.stop = function stop() {
        var computedStyle = window.getComputedStyle(this._path, null);
        var offset = computedStyle.getPropertyValue('stroke-dashoffset');
        this._path.style.strokeDashoffset = offset;

        this._setTransition('none');
        this._removeCallbacks();
    };

    // Method introduced here:
    // http://jakearchibald.com/2013/animated-line-drawing-svg/
    Path.prototype.animate = function animate(percent, opts, cb) {
        if (isFunction(opts)) {
            cb = opts;
            opts = {};
        }

        // Copy default opts to new object so defaults are not modified
        var defaultOpts = extend({}, this._opts);
        opts = extend(defaultOpts, opts);

        this._setTransition('none');

        if (cb) {
            var self = this;
            this._setCallback('transitionend', function(/* arguments */) {
                cb.apply(self, arguments);
                self._removeCallback('transitionend');
            });
        }

        // Trigger a layout so styles are calculated & the browser
        // picks up the starting position before animating
        this._path.getBoundingClientRect();

        // Animate
        var transition = 'stroke-dashoffset ' + opts.duration + 'ms ' + opts.easing;
        this._setTransition(transition);

        var length = this._path.getTotalLength();
        this._path.style.strokeDashoffset = length - (percent / 100) * length;
    };

    Path.prototype._setTransition = function _setTransition(transition) {
        for (var i = 0; i < PREFIXES.length; ++i) {
            var prefix = PREFIXES[i].toUpperCase() + PREFIXES[i].substr(1);
            this._path.style[prefix + 'Transition'] = transition;
        }

        this._path.style.transition = transition;
    };

    Path.prototype._setCallback = function _setCallback(eventName, cb) {
        this._removeCallback(eventName);
        this._path.addEventListener(eventName, cb);
        this._callbacks[eventName] = cb;
    };

    Path.prototype._removeCallbacks = function _removeCallbacks() {
        for (var eventName in this._callbacks) {
            if (this._callbacks.hasOwnProperty(eventName)) {
                this._removeCallback(eventName);
            }
        }
    };

    Path.prototype._removeCallback = function _removeCallback(eventName) {
        if (this._callbacks.hasOwnProperty(eventName)) {
            this._path.removeEventListener(eventName, this._callbacks[eventName]);
        }
    };

    // Utility functions

    // Copy all attributes from source object to destination object.
    // destination object is mutated.
    function extend(destination, source) {
        destination = destination || {};

        for (var attrName in source) {
            if (source.hasOwnProperty(attrName)) {
                destination[attrName] = source[attrName];
            }
        }

        return destination;
    }

    function isString(obj) {
        return typeof obj === 'string' || obj instanceof String;
    }

    function isFunction(obj) {
        return typeof obj === "function";
    }

    // Expose modules
    root.ProgressBar = {
        Circle: Circle,
        Square: Square,
        Path: Path
    };
})(window);
<commit_msg>Add AMD support<commit_after>(function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define('progressbar', [], function() {
            return factory();
        });
    } else {
        // Browser globals
        root.ProgressBar = factory();
    }
}(this, function() {

    var PREFIXES = 'webkit moz o ms'.split(' ');

    // Base object for different progress bar shapes
    var Progress = function(container, opts) {
        // Prevent calling constructor without parameters so inheritance
        // works correctly
        if (arguments.length === 0) return;

        var svgView = this._createSvgView(opts);

        var element;
        if (isString(container)) {
            element = document.querySelector(container);
        } else {
            element = container;
        }
        element.appendChild(svgView.svg);

        this._path = new Path(svgView.path, opts);
    };

    Progress.prototype.animate = function animate(percent, opts, cb) {
        this._path.stop();
        this._path.animate(percent, opts, cb);
    };

    Progress.prototype.stop = function stop() {
        this._path.stop();
    };

    Progress.prototype.set = function set(percent) {
        this._path.set(percent);
    };

    Progress.prototype._createSvgView = function _createSvgView(opts) {
        opts = extend({
            color: "#555",
            strokeWidth: 1.0,
            trailColor: "#f4f4f4",
            fill: null
        }, opts);

        var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        svg.setAttribute("viewBox", "0 0 100 100");

        if (opts.trailColor) {
            var trailOpts = extend({}, opts);
            trailOpts.color = opts.trailColor;
            var trailPath = this._createPath(trailOpts);
            svg.appendChild(trailPath);
        }

        var path = this._createPath(opts);
        svg.appendChild(path);

        return {
            svg: svg,
            path: path
        };
    };

    Progress.prototype._createPath = function _createPath(opts) {
        var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
        path.setAttributeNS(null, "d", this._pathString(opts));
        path.setAttributeNS(null, "stroke", opts.color);
        path.setAttributeNS(null, "stroke-width", opts.strokeWidth);

        if (opts.fill) {
            path.setAttributeNS(null, "fill", opts.fill);
        } else {
            path.setAttributeNS(null, "fill-opacity", "0");
        }

        return path;
    };

    Progress.prototype._pathString = function _pathString(opts) {
        throw new Error("Override this function for each progress bar");
    };

    // Progress bar shapes

    var Circle = function(container, options) {
        Progress.apply(this, arguments);
    };

    Circle.prototype = new Progress();
    Circle.prototype.constructor = Circle;

    Circle.prototype._pathString = function _pathString(opts) {
        // Use two arcs to form a circle
        // See this answer http://stackoverflow.com/a/10477334/1446092
        var pathString = "M 50,50 m 0,-{r} a {r},{r} 0 1 1 0,{r*2} a {r},{r} 0 1 1 0,-{r*2}";
        var r = 50 - opts.strokeWidth / 2;
        pathString = pathString.replace(/\{r\}/g, r);
        pathString = pathString.replace(/\{r\*2\}/g, r * 2);
        return pathString;
    };

    var Square = function(container, options) {
        Progress.apply(this, arguments);
    };

    Square.prototype = new Progress();
    Square.prototype.constructor = Square;

    Square.prototype._pathString = function _pathString(opts) {
        var pathString = "M 0,{s/2} L {w},{s/2} L {w},{w} L {s/2},{w} L {s/2},{s}";
        var w = 100 - opts.strokeWidth / 2;
        pathString = pathString.replace(/\{w\}/g, w);
        pathString = pathString.replace(/\{s\}/g, opts.strokeWidth);
        pathString = pathString.replace(/\{s\/2\}/g, opts.strokeWidth / 2);
        return pathString;
    };

    // Lower level API to animate any kind of svg path

    var Path = function(path, opts) {
        opts = extend({
            duration: 800,
            easing: "ease-in-out"
        }, opts);

        this._path = path;
        this._opts = opts;
        this._callbacks = {};

        // Set up the starting positions
        var length = this._path.getTotalLength();
        this._path.style.strokeDasharray = length + ' ' + length;
        this._path.style.strokeDashoffset = length;
    };

    Path.prototype.set = function set(percent) {
        this._setTransition('none');

        var length = this._path.getTotalLength();
        this._path.style.strokeDashoffset = length - (percent / 100) * length;
    };

    Path.prototype.stop = function stop() {
        var computedStyle = window.getComputedStyle(this._path, null);
        var offset = computedStyle.getPropertyValue('stroke-dashoffset');
        this._path.style.strokeDashoffset = offset;

        this._setTransition('none');
        this._removeCallbacks();
    };

    // Method introduced here:
    // http://jakearchibald.com/2013/animated-line-drawing-svg/
    Path.prototype.animate = function animate(percent, opts, cb) {
        if (isFunction(opts)) {
            cb = opts;
            opts = {};
        }

        // Copy default opts to new object so defaults are not modified
        var defaultOpts = extend({}, this._opts);
        opts = extend(defaultOpts, opts);

        this._setTransition('none');

        if (cb) {
            var self = this;
            this._setCallback('transitionend', function(/* arguments */) {
                cb.apply(self, arguments);
                self._removeCallback('transitionend');
            });
        }

        // Trigger a layout so styles are calculated & the browser
        // picks up the starting position before animating
        this._path.getBoundingClientRect();

        // Animate
        var transition = 'stroke-dashoffset ' + opts.duration + 'ms ' + opts.easing;
        this._setTransition(transition);

        var length = this._path.getTotalLength();
        this._path.style.strokeDashoffset = length - (percent / 100) * length;
    };

    Path.prototype._setTransition = function _setTransition(transition) {
        for (var i = 0; i < PREFIXES.length; ++i) {
            var prefix = PREFIXES[i].toUpperCase() + PREFIXES[i].substr(1);
            this._path.style[prefix + 'Transition'] = transition;
        }

        this._path.style.transition = transition;
    };

    Path.prototype._setCallback = function _setCallback(eventName, cb) {
        this._removeCallback(eventName);
        this._path.addEventListener(eventName, cb);
        this._callbacks[eventName] = cb;
    };

    Path.prototype._removeCallbacks = function _removeCallbacks() {
        for (var eventName in this._callbacks) {
            if (this._callbacks.hasOwnProperty(eventName)) {
                this._removeCallback(eventName);
            }
        }
    };

    Path.prototype._removeCallback = function _removeCallback(eventName) {
        if (this._callbacks.hasOwnProperty(eventName)) {
            this._path.removeEventListener(eventName, this._callbacks[eventName]);
        }
    };

    // Utility functions

    // Copy all attributes from source object to destination object.
    // destination object is mutated.
    function extend(destination, source) {
        destination = destination || {};

        for (var attrName in source) {
            if (source.hasOwnProperty(attrName)) {
                destination[attrName] = source[attrName];
            }
        }

        return destination;
    }

    function isString(obj) {
        return typeof obj === 'string' || obj instanceof String;
    }

    function isFunction(obj) {
        return typeof obj === "function";
    }

    // Expose modules
    var ProgressBar = {
        Circle: Circle,
        Square: Square,
        Path: Path
    };

    return ProgressBar;
}));
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Red Hat Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var log = require('./log.js').logger();
var https = require('https');
var fs = require('fs');
var util = require('util');
var events = require('events');
var querystring = require('querystring');
var set = require('./set.js');
var myutils = require('./utils.js');
var myevents = require('./events.js');

function watch_handler(collection) {
    var partial = undefined;
    return function (msg) {
        var content = partial ? partial + msg : msg;
        var start = 0;
        for (var end = content.indexOf('\n', start); end > 0; start = end + 1, end = start < content.length ? content.indexOf('\n', start) : -1) {
            var line = content.substring(start, end);
            var event;
            try {
                event = JSON.parse(line);
            } catch (e) {
                log.warn('Could not parse message as JSON (%s), assuming incomplete: %s', e, line);
                break;
            }
            collection[event.type.toLowerCase()](event.object);
        }
        partial = content.substring(start);
    }
}

var cache = {};

function read(file) {
    if (cache[file] === undefined) {
        cache[file] = fs.readFileSync(file);
        setTimeout(function () { cache[file] = undefined; }, 1000*60*5);//force refresh every 5 minutes
    }
    return cache[file];
}

function get_options(options, path) {
    return {
        hostname: options.host || process.env.KUBERNETES_SERVICE_HOST,
        port: options.port || process.env.KUBERNETES_SERVICE_PORT,
        rejectUnauthorized: false,
        path: options.path || path,
        headers: {
            'Authorization': 'Bearer ' + (options.token || process.env.KUBERNETES_TOKEN || read('/var/run/secrets/kubernetes.io/serviceaccount/token')),
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        }
    };
}

function get_path(base, resource, options) {
    var namespace = options.namespace || process.env.KUBERNETES_NAMESPACE || read('/var/run/secrets/kubernetes.io/serviceaccount/namespace');
    var path = base + namespace + '/' + resource;
    var queryParams = {};
    if (options.selector) {
        queryParams.labelSelector = options.selector;
    }
    if (options.requestTimeout) {
        queryParams.timeoutSeconds = options.requestTimeout;
    }
    if (Object.keys(queryParams).length) {
        path += '?' + querystring.stringify(queryParams);
    }
    return path;
}

function list_options(resource, baseOptions) {
    var base = resource.startsWith("address") ? '/apis/enmasse.io/v1beta1/namespaces/' : '/api/v1/namespaces/';
    let path = get_path(base, resource, baseOptions);
    var options = get_options(baseOptions, path);
    return myutils.merge({requestTimeout: options.requestTimeout || process.env.REQUEST_TIMEOUT || 120}, options);
}

function watch_options(resource, baseOptions) {
    var base = resource.startsWith("address") ? '/apis/enmasse.io/v1beta1/watch/namespaces/' : '/api/v1/watch/namespaces/';
    var options = get_options(baseOptions, get_path(base, resource, includeResyncInterval(baseOptions)));
    return includeResyncInterval(options);
}

function includeResyncInterval(options) {
    return myutils.merge({requestTimeout: options.requestTimeout || process.env.RESYNC_INTERVAL}, options);
}

function apply_timeout(opts, request) {
    if (opts.requestTimeout !== undefined) {
        request.setTimeout(opts.requestTimeout * 1000, function () {
            log.info('response %s timeout (%ds)', opts.path, opts.requestTimeout);
            request.abort();
        });
    }
}

function do_get_with_options(opts) {
    return new Promise(function (resolve, reject) {
        var request = https.get(opts, function(response) {
	    log.info('GET %s => %s ', opts.path, response.statusCode);
	    response.setEncoding('utf8');
            var data = '';
	    response.on('data', function (chunk) { data += chunk; });
	    response.on('end', function () {
                if (response.statusCode === 200) {
                    try {
                        resolve(JSON.parse(data));
                    } catch (e) {
                        reject(new Error(util.format('Could not parse message as JSON (%s): %s', e, data)));
                    }
                } else {
                    var error = new Error(util.format('Failed to retrieve %s: %s %s', opts.path, response.statusCode, data));
                    error.statusCode = response.statusCode;
                    reject(error);
                }
	    });
        });
        request.on('error', reject);
        apply_timeout(opts, request);
    });
};

function do_get(resource, options) {
    var opts = list_options(resource, options || {});
    return do_get_with_options(opts);
};

function do_get_raw(path, options) {
    var opts = get_options(options, path);
    return do_get_with_options(opts);
}

function do_request(method, input, opts, return_data = false) {
    return new Promise(function (resolve, reject) {
        opts.method = method;
        var request = https.request(opts, function (response) {
            var body = '';
            response.on('data', function (chunk) {
                body += chunk;
            });
            response.on('end', function () {
                var statusCode = response.statusCode;
                log.info('%s %s => %s', opts.method, opts.path, statusCode);
                var statusObject = {
                    statusCode: statusCode,
                    body: body,
                };
                if (statusCode >= 400) {
                    reject(statusObject);
                } else {
                    resolve(return_data ? statusObject : statusCode);
                }
            });
        });
        request.on('error', reject);
        apply_timeout(opts, request);
        if (input) request.write(input);
        request.end();
    });
};

function do_post(resource, object, options) {
    var opts = list_options(resource, options || {});
    return do_request('POST', JSON.stringify(object), opts);
};

function do_put(resource, object, options) {
    var opts = list_options(resource, options || {});
    return do_request('PUT', JSON.stringify(object), opts);
};

function do_delete(resource, options) {
    var opts = list_options(resource, options || {});
    return do_request('DELETE', undefined, opts);
};

function do_is_openshift() {
    var opts = get_options({}, "/apis/user.openshift.io");
    return new Promise(function (resolve, reject) {
        do_get_with_options(opts)
            .then(() => {resolve(true)})
            .catch((e) => {
                if (e.statusCode === 404) {
                    resolve(false);
                } else {
                    reject(e);
                }});
    });
}

function name_compare(a, b) {
    return myutils.string_compare(a.metadata.name, b.metadata.name);
};

function Watcher (resource, options) {
    events.EventEmitter.call(this);
    this.closed = false;
    this.resource = resource;
    this.options = options;
    this.set = set.sorted_object_set(name_compare);
    this.delay = 0;
    this.notify = myutils.coalesce(this._notify.bind(this), 100, 5000);
}

util.inherits(Watcher, events.EventEmitter);

Watcher.prototype._notify = function () {
    var self = this;
    setImmediate( function () {
        self.emit('updated', self.set.to_array());
    });
};

Watcher.prototype.list = function () {
    var self = this;
    do_get(this.resource, this.options).then(function (result) {
        self.delay = 0;
        self.set.reset(result.items);
        self.notify();
        if (!self.closed) {
            log.debug('list retrieved; watching...');
            self.watch();
        } else {
            self.emit('closed');
        }
    }).catch(function (error) {
        log.error('failed to retrieve %s: %s (retry in %d seconds)', self.resource, error, self.delay);
        setTimeout(self.list.bind(self), self.delay * 1000);
        self.delay = Math.min(30, self.delay + 1);
    });
};

Watcher.prototype.watch = function () {
    var self = this;
    var opts = watch_options(this.resource, this.options);
    var request = https.get(opts, function(response) {
        log.info('GET %s => %s ', opts.path, response.statusCode);
        response.setEncoding('utf8');
        response.on('data', watch_handler(self));
    });
    request.on('error', function(e) {
        log.error('error on watch %s: %s', opts.path, e);
    });
    request.on('close', function () {
        if (!self.closed) {
            log.debug('response %s ended; reconnecting...', opts.path);
            self.list();
        } else {
            self.emit('closed');
        }
    });
    apply_timeout(opts, request);
};

function matcher(object) {
    return function (o) { return o.metadata.name === object.metadata.name; };
};

Watcher.prototype.added = function (object) {
    if (this.set.insert(object)) {
        this.notify();
        return true;
    } else {
        return false;
    }
};

Watcher.prototype.modified = function (object) {
    if (this.set.replace(object)) {
        this.notify();
        return true;
    } else {
        return false;
    }
};

Watcher.prototype.deleted = function (object) {
    if (this.set.remove(object)) {
        this.notify();
        return true;
    } else {
        return false;
    }
};

Watcher.prototype.close = function () {
    this.closed = true;
    var self = this;
    return new Promise(function (resolve) {
        self.once('closed', function () {
            resolve();
        });
    });
};

module.exports.get_path = get_path;
module.exports.get_raw = do_get_raw;
module.exports.is_openshift = do_is_openshift;

module.exports.get = function (resource, options) {
    return do_get(resource, options);
};

module.exports.post = function (resource, object, options) {
    return do_post(resource, object, options);
};

module.exports.delete_resource = function(resource, options) {
    return do_delete(resource, options);
}

module.exports.watch = function (resource, options) {
    var w = new Watcher(resource, options);
    w.list();
    return w;
};

module.exports.update = function (resource, transform, options) {
    return do_get(resource, options).then(function (original) {
        var updated = transform(original);
        if (updated !== undefined) {
            return do_put(resource, updated, options);
        } else {
            return 304;
        }
    });
};

function post_new_event(event) {
    return do_post('events', event).then(function (code, message) {
        if (code >= 400) log.warn('failed to post new event: %j %s %s', event, code, message);
        else log.debug('posted new event: %j %s %s', event, code);
    }).catch(function (error) {
        log.warn(' failed to post event: %j %s', event, error);
    });
}

module.exports.post_event = function (event) {
    event.involvedObject.namespace = process.env.KUBERNETES_NAMESPACE || read('/var/run/secrets/kubernetes.io/serviceaccount/namespace').toString();
    return do_get(util.format('events/%s', event.metadata.name)).then(function (original) {
        if (myevents.equivalent(event, original)) {
            original.count++;
            original.lastTimestamp = event.lastTimestamp;
            return do_put(util.format('events/%s', event.metadata.name), original).then(function (code, message) {
                log.debug('updated existing event: %j %s %s', event, code, message);
            });
        } else {
            return post_new_event(event);
        }
    }).catch(function () {
        return post_new_event(event);
    });
};

module.exports.get_messaging_route_hostname = function (options) {
    if (options.MESSAGING_ROUTE_HOSTNAME === undefined && options.KUBERNETES_SERVICE_HOST !== undefined) {
        var messaging_route_name = options.MESSAGING_ROUTE_NAME || 'messaging-' + options.INFRA_UUID;
        var opts = get_options(options, get_path('/oapi/v1/namespaces/', 'routes/' + messaging_route_name, options));
        return do_get_with_options(opts).then(function (definition) {
            return definition.spec.host;
        }).catch(function () {
            log.info('could not retrieve messaging route hostname');
            return undefined;
        });
    } else {
        return Promise.resolve(options.MESSAGING_ROUTE_HOSTNAME);
    }
};

module.exports.self_subject_access_review = function (options, namespace, verb, group, resource) {

    var opts = get_options(options, "/apis/authorization.k8s.io/v1/selfsubjectaccessreviews");
    var object = {
        kind: "SelfSubjectAccessReview",
        apiVersion: "authorization.k8s.io/v1",
        spec: {
            resourceAttributes: {
                namespace: namespace,
                verb: verb,
                group: group,
                resource: resource
            }
        },
        status: {allowed: false}
    };

    return new Promise(function (resolve, reject) {
        do_request('POST', JSON.stringify(object), opts, true).then(({statusCode, body}) =>
        {
            try {
                if (body) {
                    var review = JSON.parse(body);
                    if (review && "status" in review) {
                        var status = review["status"];
                        var allowed = status["allowed"];
                        var reason = status["reason"];
                        resolve({allowed, reason});
                        return;
                    }
                    reject(new Error("Unexpectedly formed SelfSubjectAccessReview response  : " + body));
                } else {
                    reject(new Error("Unexpectedly SelfSubjectAccessReview response status code  : " + statusCode + " response body" + body));
                }
            } catch (e) {
                reject(e);
            }
        }).catch((e) => {
            reject(e);
        });
    });
};

module.exports.whoami = function (options) {
    var opts = get_options(options, "/apis/user.openshift.io/v1/users/~");
    return new Promise(function (resolve, reject) {
        do_request('GET', null, opts, true).then(({statusCode, body}) =>
        {
            try {
                if (body) {
                    var user = JSON.parse(body);
                    if (user && "metadata" in user) {
                        resolve({username: user.metadata.name});
                        return;
                    }
                    reject(new Error("Unexpectedly formed User response  : " + body));
                } else {
                    reject(new Error("Unexpectedly User response status code  : " + statusCode + " response body" + body));
                }
            } catch (e) {
                reject(e);
            }
        }).catch((e) => {
            reject(e);
        });
    });
};

<commit_msg>Refactored condition for readability.<commit_after>/*
 * Copyright 2017 Red Hat Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var log = require('./log.js').logger();
var https = require('https');
var fs = require('fs');
var util = require('util');
var events = require('events');
var querystring = require('querystring');
var set = require('./set.js');
var myutils = require('./utils.js');
var myevents = require('./events.js');

function watch_handler(collection) {
    var partial = undefined;
    return function (msg) {
        var content = partial ? partial + msg : msg;
        var start = 0;
        for (var end = content.indexOf('\n', start); end > 0; start = end + 1, end = start < content.length ? content.indexOf('\n', start) : -1) {
            var line = content.substring(start, end);
            var event;
            try {
                event = JSON.parse(line);
            } catch (e) {
                log.warn('Could not parse message as JSON (%s), assuming incomplete: %s', e, line);
                break;
            }
            collection[event.type.toLowerCase()](event.object);
        }
        partial = content.substring(start);
    }
}

var cache = {};

function read(file) {
    if (cache[file] === undefined) {
        cache[file] = fs.readFileSync(file);
        setTimeout(function () { cache[file] = undefined; }, 1000*60*5);//force refresh every 5 minutes
    }
    return cache[file];
}

function get_options(options, path) {
    return {
        hostname: options.host || process.env.KUBERNETES_SERVICE_HOST,
        port: options.port || process.env.KUBERNETES_SERVICE_PORT,
        rejectUnauthorized: false,
        path: options.path || path,
        headers: {
            'Authorization': 'Bearer ' + (options.token || process.env.KUBERNETES_TOKEN || read('/var/run/secrets/kubernetes.io/serviceaccount/token')),
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        }
    };
}

function get_path(base, resource, options) {
    var namespace = options.namespace || process.env.KUBERNETES_NAMESPACE || read('/var/run/secrets/kubernetes.io/serviceaccount/namespace');
    var path = base + namespace + '/' + resource;
    var queryParams = {};
    if (options.selector) {
        queryParams.labelSelector = options.selector;
    }
    if (options.requestTimeout) {
        queryParams.timeoutSeconds = options.requestTimeout;
    }
    if (Object.keys(queryParams).length > 0) {
        path += '?' + querystring.stringify(queryParams);
    }
    return path;
}

function list_options(resource, baseOptions) {
    var base = resource.startsWith("address") ? '/apis/enmasse.io/v1beta1/namespaces/' : '/api/v1/namespaces/';
    let path = get_path(base, resource, baseOptions);
    var options = get_options(baseOptions, path);
    return myutils.merge({requestTimeout: options.requestTimeout || process.env.REQUEST_TIMEOUT || 120}, options);
}

function watch_options(resource, baseOptions) {
    var base = resource.startsWith("address") ? '/apis/enmasse.io/v1beta1/watch/namespaces/' : '/api/v1/watch/namespaces/';
    var options = get_options(baseOptions, get_path(base, resource, includeResyncInterval(baseOptions)));
    return includeResyncInterval(options);
}

function includeResyncInterval(options) {
    return myutils.merge({requestTimeout: options.requestTimeout || process.env.RESYNC_INTERVAL}, options);
}

function apply_timeout(opts, request) {
    if (opts.requestTimeout !== undefined) {
        request.setTimeout(opts.requestTimeout * 1000, function () {
            log.info('response %s timeout (%ds)', opts.path, opts.requestTimeout);
            request.abort();
        });
    }
}

function do_get_with_options(opts) {
    return new Promise(function (resolve, reject) {
        var request = https.get(opts, function(response) {
	    log.info('GET %s => %s ', opts.path, response.statusCode);
	    response.setEncoding('utf8');
            var data = '';
	    response.on('data', function (chunk) { data += chunk; });
	    response.on('end', function () {
                if (response.statusCode === 200) {
                    try {
                        resolve(JSON.parse(data));
                    } catch (e) {
                        reject(new Error(util.format('Could not parse message as JSON (%s): %s', e, data)));
                    }
                } else {
                    var error = new Error(util.format('Failed to retrieve %s: %s %s', opts.path, response.statusCode, data));
                    error.statusCode = response.statusCode;
                    reject(error);
                }
	    });
        });
        request.on('error', reject);
        apply_timeout(opts, request);
    });
};

function do_get(resource, options) {
    var opts = list_options(resource, options || {});
    return do_get_with_options(opts);
};

function do_get_raw(path, options) {
    var opts = get_options(options, path);
    return do_get_with_options(opts);
}

function do_request(method, input, opts, return_data = false) {
    return new Promise(function (resolve, reject) {
        opts.method = method;
        var request = https.request(opts, function (response) {
            var body = '';
            response.on('data', function (chunk) {
                body += chunk;
            });
            response.on('end', function () {
                var statusCode = response.statusCode;
                log.info('%s %s => %s', opts.method, opts.path, statusCode);
                var statusObject = {
                    statusCode: statusCode,
                    body: body,
                };
                if (statusCode >= 400) {
                    reject(statusObject);
                } else {
                    resolve(return_data ? statusObject : statusCode);
                }
            });
        });
        request.on('error', reject);
        apply_timeout(opts, request);
        if (input) request.write(input);
        request.end();
    });
};

function do_post(resource, object, options) {
    var opts = list_options(resource, options || {});
    return do_request('POST', JSON.stringify(object), opts);
};

function do_put(resource, object, options) {
    var opts = list_options(resource, options || {});
    return do_request('PUT', JSON.stringify(object), opts);
};

function do_delete(resource, options) {
    var opts = list_options(resource, options || {});
    return do_request('DELETE', undefined, opts);
};

function do_is_openshift() {
    var opts = get_options({}, "/apis/user.openshift.io");
    return new Promise(function (resolve, reject) {
        do_get_with_options(opts)
            .then(() => {resolve(true)})
            .catch((e) => {
                if (e.statusCode === 404) {
                    resolve(false);
                } else {
                    reject(e);
                }});
    });
}

function name_compare(a, b) {
    return myutils.string_compare(a.metadata.name, b.metadata.name);
};

function Watcher (resource, options) {
    events.EventEmitter.call(this);
    this.closed = false;
    this.resource = resource;
    this.options = options;
    this.set = set.sorted_object_set(name_compare);
    this.delay = 0;
    this.notify = myutils.coalesce(this._notify.bind(this), 100, 5000);
}

util.inherits(Watcher, events.EventEmitter);

Watcher.prototype._notify = function () {
    var self = this;
    setImmediate( function () {
        self.emit('updated', self.set.to_array());
    });
};

Watcher.prototype.list = function () {
    var self = this;
    do_get(this.resource, this.options).then(function (result) {
        self.delay = 0;
        self.set.reset(result.items);
        self.notify();
        if (!self.closed) {
            log.debug('list retrieved; watching...');
            self.watch();
        } else {
            self.emit('closed');
        }
    }).catch(function (error) {
        log.error('failed to retrieve %s: %s (retry in %d seconds)', self.resource, error, self.delay);
        setTimeout(self.list.bind(self), self.delay * 1000);
        self.delay = Math.min(30, self.delay + 1);
    });
};

Watcher.prototype.watch = function () {
    var self = this;
    var opts = watch_options(this.resource, this.options);
    var request = https.get(opts, function(response) {
        log.info('GET %s => %s ', opts.path, response.statusCode);
        response.setEncoding('utf8');
        response.on('data', watch_handler(self));
    });
    request.on('error', function(e) {
        log.error('error on watch %s: %s', opts.path, e);
    });
    request.on('close', function () {
        if (!self.closed) {
            log.debug('response %s ended; reconnecting...', opts.path);
            self.list();
        } else {
            self.emit('closed');
        }
    });
    apply_timeout(opts, request);
};

function matcher(object) {
    return function (o) { return o.metadata.name === object.metadata.name; };
};

Watcher.prototype.added = function (object) {
    if (this.set.insert(object)) {
        this.notify();
        return true;
    } else {
        return false;
    }
};

Watcher.prototype.modified = function (object) {
    if (this.set.replace(object)) {
        this.notify();
        return true;
    } else {
        return false;
    }
};

Watcher.prototype.deleted = function (object) {
    if (this.set.remove(object)) {
        this.notify();
        return true;
    } else {
        return false;
    }
};

Watcher.prototype.close = function () {
    this.closed = true;
    var self = this;
    return new Promise(function (resolve) {
        self.once('closed', function () {
            resolve();
        });
    });
};

module.exports.get_path = get_path;
module.exports.get_raw = do_get_raw;
module.exports.is_openshift = do_is_openshift;

module.exports.get = function (resource, options) {
    return do_get(resource, options);
};

module.exports.post = function (resource, object, options) {
    return do_post(resource, object, options);
};

module.exports.delete_resource = function(resource, options) {
    return do_delete(resource, options);
}

module.exports.watch = function (resource, options) {
    var w = new Watcher(resource, options);
    w.list();
    return w;
};

module.exports.update = function (resource, transform, options) {
    return do_get(resource, options).then(function (original) {
        var updated = transform(original);
        if (updated !== undefined) {
            return do_put(resource, updated, options);
        } else {
            return 304;
        }
    });
};

function post_new_event(event) {
    return do_post('events', event).then(function (code, message) {
        if (code >= 400) log.warn('failed to post new event: %j %s %s', event, code, message);
        else log.debug('posted new event: %j %s %s', event, code);
    }).catch(function (error) {
        log.warn(' failed to post event: %j %s', event, error);
    });
}

module.exports.post_event = function (event) {
    event.involvedObject.namespace = process.env.KUBERNETES_NAMESPACE || read('/var/run/secrets/kubernetes.io/serviceaccount/namespace').toString();
    return do_get(util.format('events/%s', event.metadata.name)).then(function (original) {
        if (myevents.equivalent(event, original)) {
            original.count++;
            original.lastTimestamp = event.lastTimestamp;
            return do_put(util.format('events/%s', event.metadata.name), original).then(function (code, message) {
                log.debug('updated existing event: %j %s %s', event, code, message);
            });
        } else {
            return post_new_event(event);
        }
    }).catch(function () {
        return post_new_event(event);
    });
};

module.exports.get_messaging_route_hostname = function (options) {
    if (options.MESSAGING_ROUTE_HOSTNAME === undefined && options.KUBERNETES_SERVICE_HOST !== undefined) {
        var messaging_route_name = options.MESSAGING_ROUTE_NAME || 'messaging-' + options.INFRA_UUID;
        var opts = get_options(options, get_path('/oapi/v1/namespaces/', 'routes/' + messaging_route_name, options));
        return do_get_with_options(opts).then(function (definition) {
            return definition.spec.host;
        }).catch(function () {
            log.info('could not retrieve messaging route hostname');
            return undefined;
        });
    } else {
        return Promise.resolve(options.MESSAGING_ROUTE_HOSTNAME);
    }
};

module.exports.self_subject_access_review = function (options, namespace, verb, group, resource) {

    var opts = get_options(options, "/apis/authorization.k8s.io/v1/selfsubjectaccessreviews");
    var object = {
        kind: "SelfSubjectAccessReview",
        apiVersion: "authorization.k8s.io/v1",
        spec: {
            resourceAttributes: {
                namespace: namespace,
                verb: verb,
                group: group,
                resource: resource
            }
        },
        status: {allowed: false}
    };

    return new Promise(function (resolve, reject) {
        do_request('POST', JSON.stringify(object), opts, true).then(({statusCode, body}) =>
        {
            try {
                if (body) {
                    var review = JSON.parse(body);
                    if (review && "status" in review) {
                        var status = review["status"];
                        var allowed = status["allowed"];
                        var reason = status["reason"];
                        resolve({allowed, reason});
                        return;
                    }
                    reject(new Error("Unexpectedly formed SelfSubjectAccessReview response  : " + body));
                } else {
                    reject(new Error("Unexpectedly SelfSubjectAccessReview response status code  : " + statusCode + " response body" + body));
                }
            } catch (e) {
                reject(e);
            }
        }).catch((e) => {
            reject(e);
        });
    });
};

module.exports.whoami = function (options) {
    var opts = get_options(options, "/apis/user.openshift.io/v1/users/~");
    return new Promise(function (resolve, reject) {
        do_request('GET', null, opts, true).then(({statusCode, body}) =>
        {
            try {
                if (body) {
                    var user = JSON.parse(body);
                    if (user && "metadata" in user) {
                        resolve({username: user.metadata.name});
                        return;
                    }
                    reject(new Error("Unexpectedly formed User response  : " + body));
                } else {
                    reject(new Error("Unexpectedly User response status code  : " + statusCode + " response body" + body));
                }
            } catch (e) {
                reject(e);
            }
        }).catch((e) => {
            reject(e);
        });
    });
};

<|endoftext|>


<commit_before>/****************************
Name: stellar.donate.js
Author: saza.com.ng
Desc: Enables transfer of lumens
to a specific account. Can be integrated
into a website for donations.
Note: Use this plugin over https connection
**************************/

jQuery(document).ready( function($){
  var apiURL = "https://saza.com.ng:8888/donate";
  var statusMsg = "Processing Payment";
	var stellarDonate = $('#stellar-donate');
	var destAcct = stellarDonate.data("dest");
  console.log(destAcct);

	var formTemplate =`

Donate to ${destAcct}

  <form id="stellar-donate-form" class="form-horizontal" name="stellarDonateForm" method="POST">

        <input type="number" class="form-control" id="sdfAmount" name="amount" placeholder="Amount in XLM" required/>
        Enter the amount in XLM

        <input type="text" class="form-control" id="sdfSeed" name="srcSeed"  placeholder="Your Stellar Account Seed" required/>
        Enter Seed to enable us verify account ownership. This is not saved

    <input type="hidden" id="sdfDest" name="destAcct"  value="${destAcct}"/>
    <button type="submit" class="btn btn-success ">Send</button>
  </form>

  `;

	stellarDonate.html(formTemplate);
  stellarDonate.append('Powered by SAZA');

  // Detect when form is submitted and process payment
  $("#stellar-donate-form" ).submit(function( event ) {

    // Stop form from submitting normally
    event.preventDefault();
    $('#sdmsg').html('
'+statusMsg+'
')

    // Send the data using post
    var posting = $.post( apiURL, $(this).serialize() );
    var response = "";

    posting.done(function( data ) {
      console.log("done", data);
      $('#sdmsg').html('
'+data.content.message+'
');

    });

    posting.fail(function( data ) {
      console.log("fail", JSON.parse(data.responseText));
      response = JSON.parse(data.responseText);
      $('#sdfAmount').val("");
      $('#sdfSeed').val("");
      $('#sdmsg').html('
'+response.content.message+'
');
    });

  });

});
<commit_msg>Removed console logs<commit_after>/****************************
Name: stellar.donate.js
Author: saza.com.ng
Desc: Enables transfer of lumens
to a specific account. Can be integrated
into a website for donations.
Note: Use this plugin over https connection
**************************/

jQuery(document).ready( function($){
  var apiURL = "https://saza.com.ng:8888/donate";
  var statusMsg = "Processing Payment";
	var stellarDonate = $('#stellar-donate');
	var destAcct = stellarDonate.data("dest");

	var formTemplate =`

Donate to ${destAcct}

  <form id="stellar-donate-form" class="form-horizontal" name="stellarDonateForm" method="POST">

        <input type="number" class="form-control" id="sdfAmount" name="amount" placeholder="Amount in XLM" required/>
        Enter the amount in XLM

        <input type="text" class="form-control" id="sdfSeed" name="srcSeed"  placeholder="Your Stellar Account Seed" required/>
        Enter Seed to enable us verify account ownership. This is not saved

    <input type="hidden" id="sdfDest" name="destAcct"  value="${destAcct}"/>
    <button type="submit" class="btn btn-success ">Send</button>
  </form>

  `;

  stellarDonate.html(formTemplate);
  stellarDonate.append('Powered by SAZA');

  // Detect when form is submitted and process payment
  $("#stellar-donate-form" ).submit(function( event ) {

    // Stop form from submitting normally
    event.preventDefault();
    $('#sdmsg').html('
'+statusMsg+'
')

    // Send the data using post
    var posting = $.post( apiURL, $(this).serialize() );
    var response = "";

    posting.done(function( data ) {
      //console.log("done", data);
      $('#sdmsg').html('
'+data.content.message+'
');

    });

    posting.fail(function( data ) {
      //console.log("fail", JSON.parse(data.responseText));
      response = JSON.parse(data.responseText);
      $('#sdfAmount').val("");
      $('#sdfSeed').val("");
      $('#sdmsg').html('
'+response.content.message+'
');
    });

  });

});
<|endoftext|>


<commit_before>'use strict';

var w = 500, // width
  h = 500; // height

var x = {},
  y = [],
  z = 0,
  $ = '',
  _ = null;

var d = d3,
  ln = d.svg.line,
  rn = d.range,
  c1 = d.scale.category10,
  c2 = d.scale.category20;

d.selection.prototype.a = d.selection.prototype.attr;
d.selection.prototype.A = d.selection.prototype.append;
d.selection.prototype.s = d.selection.prototype.select;
d.selection.prototype.S = d.selection.prototype.selectAll;
d.selection.prototype.c = d.selection.prototype.call;
d.selection.prototype.C = d.selection.prototype.classed;
d.selection.prototype.e = d.selection.prototype.each;
d.selection.prototype.D = d.selection.prototype.data;
d.selection.prototype.d = d.selection.prototype.datum;
d.selection.prototype.r = d.selection.prototype.remove;
d.selection.prototype.h = d.selection.prototype.html;
d.selection.prototype.t = d.selection.prototype.text;
d.selection.prototype.o = d.selection.prototype.on;
d.selection.prototype.y = d.selection.prototype.style;

// mouse/touch positions
var mo = [0, 0], to = [];

var n = function(tuple) {
  return [
    tuple[0] / w - 0.5,
    tuple[1] / h - 0.5
  ];
}

function mouse() {
  mo = n(d.mouse(this));
}

function touch() {
  to = d3.touches(this).map(n);
  mo = to[0] || [0, 0];
}

// create a canvas
var g = d.select("body")
  .A("svg")
  .a("viewBox", '0 0 ' + w + ' ' + h)
  .o("mouseenter", mouse)
  .o("mousemove", mouse)
  .o("mouseleave", function() { mo = [0, 0]; })
  .o("touchstart", touch)
  .o("touchmove", touch)
  .o("touchend", touch)
  .A("g")
  .a("transform", "translate(" + [w / 2, h / 2] + ")");

// aliases
var a = Math.abs,
  ce = Math.ceil,
  fl = Math.floor,
  ro = Math.round,
  sq = Math.sqrt,
  lo = Math.log,
  l2 = Math.log2,
  l1 = Math.log10,
  mi = Math.min,
  ma = Math.max,
  s = Math.sin,
  c = Math.cos,
  t = Math.tan,
  as = Math.asin,
  ac = Math.acos,
  at = Math.atan,
  r = Math.random,
  e = Math.E,
  π = Math.PI;

var tr = 'transform',
  ts = function(x, y) {
    return 'translate(' + x + ',' + y + ')';
  },
  sc = function(f) {
    return 'scale(' + f + ')';
  },
  rt = function(a) {
    return 'rotate(' + a + ')';
  },
  op = 'opacity';

// datajoin utility function
function j(element) {
  return function(data) {
    var update = g.selectAll(element)
        .data(data || g.datum());
    update.e = update.enter()
      .append(element);
    update.x = update.exit();
    return update;
  }
}

var C = j('circle'),
  E = j('ellipse'),
  L = j('line'),
  P = j('path'),
  PG = j('polygon'),
  PL = j('polyline'),
  R = j('rect'),
  T = j('text'),
  G = j('g');

// render loop
d3.timer(function(t) {
  g.d([t]);
  if (window.tweet) {
    tweet(t);
  }
});
<commit_msg>Rename t(Math.tan) ta<commit_after>'use strict';

var w = 500, // width
  h = 500; // height

var x = {},
  y = [],
  z = 0,
  $ = '',
  _ = null;

var d = d3,
  ln = d.svg.line,
  rn = d.range,
  c1 = d.scale.category10,
  c2 = d.scale.category20;

d.selection.prototype.a = d.selection.prototype.attr;
d.selection.prototype.A = d.selection.prototype.append;
d.selection.prototype.s = d.selection.prototype.select;
d.selection.prototype.S = d.selection.prototype.selectAll;
d.selection.prototype.c = d.selection.prototype.call;
d.selection.prototype.C = d.selection.prototype.classed;
d.selection.prototype.e = d.selection.prototype.each;
d.selection.prototype.D = d.selection.prototype.data;
d.selection.prototype.d = d.selection.prototype.datum;
d.selection.prototype.r = d.selection.prototype.remove;
d.selection.prototype.h = d.selection.prototype.html;
d.selection.prototype.t = d.selection.prototype.text;
d.selection.prototype.o = d.selection.prototype.on;
d.selection.prototype.y = d.selection.prototype.style;

// mouse/touch positions
var mo = [0, 0], to = [];

var n = function(tuple) {
  return [
    tuple[0] / w - 0.5,
    tuple[1] / h - 0.5
  ];
}

function mouse() {
  mo = n(d.mouse(this));
}

function touch() {
  to = d3.touches(this).map(n);
  mo = to[0] || [0, 0];
}

// create a canvas
var g = d.select("body")
  .A("svg")
  .a("viewBox", '0 0 ' + w + ' ' + h)
  .o("mouseenter", mouse)
  .o("mousemove", mouse)
  .o("mouseleave", function() { mo = [0, 0]; })
  .o("touchstart", touch)
  .o("touchmove", touch)
  .o("touchend", touch)
  .A("g")
  .a("transform", "translate(" + [w / 2, h / 2] + ")");

// aliases
var a = Math.abs,
  ce = Math.ceil,
  fl = Math.floor,
  ro = Math.round,
  sq = Math.sqrt,
  lo = Math.log,
  l2 = Math.log2,
  l1 = Math.log10,
  mi = Math.min,
  ma = Math.max,
  s = Math.sin,
  c = Math.cos,
  ta = Math.tan,
  as = Math.asin,
  ac = Math.acos,
  at = Math.atan,
  r = Math.random,
  e = Math.E,
  π = Math.PI;

var tr = 'transform',
  ts = function(x, y) {
    return 'translate(' + x + ',' + y + ')';
  },
  sc = function(f) {
    return 'scale(' + f + ')';
  },
  rt = function(a) {
    return 'rotate(' + a + ')';
  },
  op = 'opacity';

// datajoin utility function
function j(element) {
  return function(data) {
    var update = g.selectAll(element)
        .data(data || g.datum());
    update.e = update.enter()
      .append(element);
    update.x = update.exit();
    return update;
  }
}

var C = j('circle'),
  E = j('ellipse'),
  L = j('line'),
  P = j('path'),
  PG = j('polygon'),
  PL = j('polyline'),
  R = j('rect'),
  T = j('text'),
  G = j('g');

// render loop
d3.timer(function(t) {
  g.d([t]);
  if (window.tweet) {
    tweet(t);
  }
});
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012-2013 Vanderbilt University, All rights reserved.
 *
 * Author: Tamas Kecskes
 */

define([ "util/assert","util/guid","util/url","socket.io","worker/serverworkermanager" ], function(ASSERT,GUID,URL,IO,SWM){

    var server = function(_database,options){
        ASSERT(typeof _database === 'object');
        options = options || {};
        options.port = options.port || 80;
        options.secret = options.secret || 'this is WEBGME!!!';
        options.cookieID = options.cookieID || 'webgme';
        options.authorization = options.authorization || function(sessionID,projectName,type,callback){callback(null,true);};
        options.sessioncheck = options.sessioncheck || function(sessionID,callback){callback(null,true);};
        options.authInfo = options.authInfo || function(sessionID,projectName,callback){callback(null,{'read':true,'write':true,'delete':true});};
        options.webServerPort = options.webServerPort || 80;
        options.log = options.log || {
            debug: function (msg) {
                console.log("DEBUG - " + msg);
            },
            error: function (msg) {
                console.log("ERROR - " + msg);
            }
        };
        var _socket = null,
            _objects = {},
            _projects = {},
            /*_references = {},*/
            _databaseOpened = false,
            ERROR_DEAD_GUID = 'the given object does not exists',
            _workerManager = null;

        function getSessionID(socket){
            return socket.handshake.webGMESessionId;
        }

        function checkDatabase(callback){
            if(_databaseOpened){
                callback();
            } else {
                _databaseOpened = true;
                _database.openDatabase(function(err){
                    if(err){
                        _databaseOpened = false;
                        options.log.error(err);
                        callback(err);
                    } else {
                        callback(null);
                    }
                });
            }
        }

        function checkProject(client,projectName,callback){
            options.authorization(client,projectName,'read',function(err,cando){
                if(!err && cando === true){
                    _database.openProject(projectName,callback);
                } else {
                    err = err || 'missing necessary user rights';
                    callback(err);
                }
            });
        }

        function createProject(client,project,callback){
            options.authorization(client,project,'create',function(err,cando){
                if(!err && cando === true){
                    if(_projects[project]){
                        //TODO we should find the real reason behind collection loose
                        try{
                            _projects[project].getBranchNames(function(err,names){
                                if(err){
                                    delete _projects[project];
                                    checkProject(client,project,callback);
                                } else {
                                    callback(null,_projects[project]);
                                }
                            });
                        }
                        catch(e){
                            delete _projects[project];
                            checkProject(client,project,callback);
                        }
                        callback(null,_projects[project]);
                    } else {
                        _database.openProject(project,function(err,proj){
                            if(!err && proj){
                                _projects[project] = proj;
                                callback(null,_projects[project]);
                            } else {
                                callback(err,null);
                            }
                        });
                    }
                } else {
                    err = err || 'missing necessary user rights';
                    callback(err);
                }
            });
        }

        function open(){
            _socket = IO.listen(options.combined ? options.combined : options.port,{
                'transports': [
                    'websocket'
                ]
            });
            if(options.logger){
                _socket.set('logger',options.logger);
            }

            _socket.set('authorization',function(data,accept){
                //either the html header contains some webgme signed cookie with the sessionID
                // or the data has a webGMESession member which should also contain the sessionID - currently the same as the cookie
                if (options.session === true){
                    var sessionID;
                    if(data.webGMESessionId === undefined){
                        if(data.query.webGMESessionId && data.query.webGMESessionId !== 'undefined'){
                            sessionID = data.query.webGMESessionId;
                        }
                    }
                    if(sessionID === null || sessionID === undefined){
                        if(data.headers.cookie){
                            var cookie = URL.parseCookie(data.headers.cookie);
                            if(cookie[options.cookieID] !== undefined || cookie[options.cookieID] !== null){
                                sessionID = require('connect').utils.parseSignedCookie(cookie[options.cookieID],options.secret);
                                data.webGMESessionId = sessionID;
                            }
                        } else {
                            console.log('DEBUG COOKIE INFO', JSON.stringify(data.headers));
                            console.log('DEBUG HANDSHAKE INFO', JSON.stringify(data.query));
                            return accept(null,false);
                        }
                    }
                    options.sessioncheck(sessionID,function(err,isOk){
                        if(!err && isOk === true){
                            data.webGMESessionId = sessionID;
                            return accept(null,true);
                        } else {
                            return accept(err,false);
                        }
                    });
                } else {
                    return accept(null,true);
                }
            });

            _socket.on('connection',function(socket){
                //first we connect our socket id to the session

                socket.on('openDatabase', function(callback){
                    checkDatabase(callback);
                });

                socket.on('closeDatabase', function(callback){
                    //we ignore the close request from any client
                    //TODO check how we should function
                    /*
                    _databaseOpened = false;
                    _database.closeDatabase(callback);
                    */
                    if(typeof callback === 'function'){
                        callback(null);
                    }
                });

                socket.on('fsyncDatabase', function(callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.fsyncDatabase(callback);
                        }
                    });
                });

                socket.on('getDatabaseStatus', function(oldstatus,callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.getDatabaseStatus(oldstatus,callback);
                        }
                    });
                });

                socket.on('getProjectNames', function(callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.getProjectNames(callback);
                        }
                    });
                });

                socket.on('getAllowedProjectNames', function(callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.getProjectNames(function(err,names){
                                if(!err){
                                    var allowedNames = [];
                                    var answerNeeded = names.length;
                                    var isProjectReadable = function(name,callback){
                                        options.authInfo(getSessionID(socket),name,function(err,authObj){
                                            if(!err){
                                                if(authObj && authObj.read === true){
                                                    allowedNames.push(name);
                                                }
                                            }
                                            callback(err);
                                        });
                                    };
                                    if(answerNeeded>0){
                                        for(var i=0;i<names.length;i++){
                                            isProjectReadable(names[i],function(err){
                                                if(--answerNeeded === 0){
                                                    callback(null,allowedNames);
                                                }
                                            });
                                        }
                                    } else {
                                        callback(null,allowedNames);
                                    }
                                } else {
                                    callback(err);
                                }
                            });
                        }
                    });
                });

                socket.on('getAuthorizationInfo', function(name,callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            options.authInfo(getSessionID(socket),name,callback);
                        }
                    });
                });

                socket.on('deleteProject', function(projectName,callback){
                    options.authorization(getSessionID(socket),projectName,'delete',function(err,cando){
                        if(err || !cando){
                            callback(err);
                        } else {
                            _database.deleteProject(projectName,function(err){
                                if(err){
                                    callback(err);
                                } else {
                                    //TODO what to do with the object itself???
                                    callback(null);
                                }
                            });
                        }
                    });
                });

                socket.on('openProject', function(projectName,callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.getProjectNames(function(err,names){
                                if(names.indexOf(projectName) === -1){
                                    //project creation
                                    createProject(getSessionID(socket),projectName,callback);
                                } else {
                                    checkProject(getSessionID(socket),projectName,callback);
                                }
                            });
                        }
                    });
                });

                socket.on('closeProject', function(projectName,callback){
                    callback = callback || function() {};
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err) {
                            callback(err);
                        } else {
                            //TODO put this together
                            //var index = _references[projectName].indexOf(getSessionID(socket));
                            //_references[projectName].splice(index,1);
                            //if(_references[projectName].length === 0){
                                //delete _references[projectName];
                                //delete _projects[projectName];
                                //project.closeProject(callback);
                            //} else {
                                callback(null);
                           // }
                        }
                    });
                });

                socket.on('loadObject', function(projectName,hash,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.loadObject(hash,callback);
                        }
                    });
                });

                socket.on('insertObject', function(projectName,object,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            options.authorization(getSessionID(socket),projectName,'write',function(err,cando){
                               if(!err && cando === true){
                                   project.insertObject(object,callback);
                               } else {
                                   callback(err);
                               }
                            });
                        }
                    });
                });

                socket.on('findHash', function(projectName,beginning,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.findHash(beginning,callback);
                        }
                    });
                });

                socket.on('dumpObjects', function(projectName,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.dumpObjects(callback);
                        }
                    });
                });
                socket.on('getBranchNames', function(projectName,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.getBranchNames(callback);
                        }
                    });
                });
                socket.on('getBranchHash', function(projectName,branch,oldhash,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.getBranchHash(branch,oldhash,callback);
                        }
                    });
                });
                socket.on('setBranchHash', function(projectName,branch,oldhash,newhash,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            options.authorization(getSessionID(socket),projectName,'write',function(err,cando){
                                if(!err && cando === true){
                                    project.setBranchHash(branch,oldhash,newhash,callback);
                                } else {
                                    callback(err);
                                }
                            });
                        }
                    });
                });
                socket.on('getCommits',function(projectName,before,number,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.getCommits(before,number,callback);
                        }
                    });
                });

                //worker commands
                socket.on('simpleRequest',function(parameters,callback){
                    if(socket.handshake){
                        parameters.webGMESessionId = getSessionID(socket) || null;
                    }
                    _workerManager.request(parameters,callback);
                });

                socket.on('simpleResult',function(resultId,callback){
                    getWorkerResult(resultId,callback);
                });

                //token for REST
                socket.on('getToken',function(callback){
                    options.getToken(getSessionID(socket),callback);
                });

                socket.on('disconnect',function(){
                    //TODO temporary the disconnect function has been removed
                });
            });

            _workerManager = new SWM({
                basedir:options.basedir,
                mongoip:options.host,
                mongoport:options.port,
                mongodb:options.database,
                intoutdir:options.intoutdir,
                pluginBasePaths:options.pluginBasePaths,
                serverPort:options.webServerPort,
                sessionToUser:options.sessionToUser
            });
        }

        function close(){

            //disconnect clients
            if(_socket){
                //_socket.sockets.emit('disconnect');
                _socket.sockets.clients().forEach(function (socket){
                    socket.disconnect();
                });
                _socket.server.close();
                _socket = null;
            }

            if(_databaseOpened){
                //close projects
                for(var i in _projects){
                    _projects[i].closeProject(null);
                }

                //close database
                _database.closeDatabase(null);
            }

            _objects = {};
            _projects = {};
            //_references = {};
            _databaseOpened = false;
        }

        function getWorkerResult(resultId,callback){
            _workerManager.result(resultId,callback);
        }

        return {
            open: open,
            close: close,
            getWorkerResult: getWorkerResult
        };
    };

    return server;
});
<commit_msg>some error now also put to console for quicker noticing<commit_after>/*
 * Copyright (C) 2012-2013 Vanderbilt University, All rights reserved.
 *
 * Author: Tamas Kecskes
 */

define([ "util/assert","util/guid","util/url","socket.io","worker/serverworkermanager" ], function(ASSERT,GUID,URL,IO,SWM){

    var server = function(_database,options){
        ASSERT(typeof _database === 'object');
        options = options || {};
        options.port = options.port || 80;
        options.secret = options.secret || 'this is WEBGME!!!';
        options.cookieID = options.cookieID || 'webgme';
        options.authorization = options.authorization || function(sessionID,projectName,type,callback){callback(null,true);};
        options.sessioncheck = options.sessioncheck || function(sessionID,callback){callback(null,true);};
        options.authInfo = options.authInfo || function(sessionID,projectName,callback){callback(null,{'read':true,'write':true,'delete':true});};
        options.webServerPort = options.webServerPort || 80;
        options.log = options.log || {
            debug: function (msg) {
                console.log("DEBUG - " + msg);
            },
            error: function (msg) {
                console.log("ERROR - " + msg);
            }
        };
        var _socket = null,
            _objects = {},
            _projects = {},
            /*_references = {},*/
            _databaseOpened = false,
            ERROR_DEAD_GUID = 'the given object does not exists',
            _workerManager = null;

        function getSessionID(socket){
            return socket.handshake.webGMESessionId;
        }

        function checkDatabase(callback){
            if(_databaseOpened){
                callback();
            } else {
                _databaseOpened = true;
                _database.openDatabase(function(err){
                    if(err){
                        _databaseOpened = false;
                        //this error has to be put to console as well
                        console.log('Error in mongoDB connection initiation!!! - ', err);
                        options.log.error(err);
                        callback(err);
                    } else {
                        callback(null);
                    }
                });
            }
        }

        function checkProject(client,projectName,callback){
            options.authorization(client,projectName,'read',function(err,cando){
                if(!err && cando === true){
                    _database.openProject(projectName,callback);
                } else {
                    err = err || 'missing necessary user rights';
                    callback(err);
                }
            });
        }

        function createProject(client,project,callback){
            options.authorization(client,project,'create',function(err,cando){
                if(!err && cando === true){
                    if(_projects[project]){
                        //TODO we should find the real reason behind collection loose
                        try{
                            _projects[project].getBranchNames(function(err,names){
                                if(err){
                                    delete _projects[project];
                                    checkProject(client,project,callback);
                                } else {
                                    callback(null,_projects[project]);
                                }
                            });
                        }
                        catch(e){
                            delete _projects[project];
                            checkProject(client,project,callback);
                        }
                        callback(null,_projects[project]);
                    } else {
                        _database.openProject(project,function(err,proj){
                            if(!err && proj){
                                _projects[project] = proj;
                                callback(null,_projects[project]);
                            } else {
                                callback(err,null);
                            }
                        });
                    }
                } else {
                    err = err || 'missing necessary user rights';
                    callback(err);
                }
            });
        }

        function open(){
            _socket = IO.listen(options.combined ? options.combined : options.port,{
                'transports': [
                    'websocket'
                ]
            });
            if(options.logger){
                _socket.set('logger',options.logger);
            }

            _socket.set('authorization',function(data,accept){
                //either the html header contains some webgme signed cookie with the sessionID
                // or the data has a webGMESession member which should also contain the sessionID - currently the same as the cookie
                if (options.session === true){
                    var sessionID;
                    if(data.webGMESessionId === undefined){
                        if(data.query.webGMESessionId && data.query.webGMESessionId !== 'undefined'){
                            sessionID = data.query.webGMESessionId;
                        }
                    }
                    if(sessionID === null || sessionID === undefined){
                        if(data.headers.cookie){
                            var cookie = URL.parseCookie(data.headers.cookie);
                            if(cookie[options.cookieID] !== undefined || cookie[options.cookieID] !== null){
                                sessionID = require('connect').utils.parseSignedCookie(cookie[options.cookieID],options.secret);
                                data.webGMESessionId = sessionID;
                            }
                        } else {
                            console.log('DEBUG COOKIE INFO', JSON.stringify(data.headers));
                            console.log('DEBUG HANDSHAKE INFO', JSON.stringify(data.query));
                            return accept(null,false);
                        }
                    }
                    options.sessioncheck(sessionID,function(err,isOk){
                        if(!err && isOk === true){
                            data.webGMESessionId = sessionID;
                            return accept(null,true);
                        } else {
                            return accept(err,false);
                        }
                    });
                } else {
                    return accept(null,true);
                }
            });

            //TODO check if this really helps
            _socket.server.on('error',function(err){
                console.log("Error have been raised on socket.io level!!! - ",err);
                options.logger.error('error raised: ' + err);
            });

            _socket.on('connection',function(socket){
                //first we connect our socket id to the session

                socket.on('openDatabase', function(callback){
                    checkDatabase(callback);
                });

                socket.on('closeDatabase', function(callback){
                    //we ignore the close request from any client
                    //TODO check how we should function
                    /*
                    _databaseOpened = false;
                    _database.closeDatabase(callback);
                    */
                    if(typeof callback === 'function'){
                        callback(null);
                    }
                });

                socket.on('fsyncDatabase', function(callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.fsyncDatabase(callback);
                        }
                    });
                });

                socket.on('getDatabaseStatus', function(oldstatus,callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.getDatabaseStatus(oldstatus,callback);
                        }
                    });
                });

                socket.on('getProjectNames', function(callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.getProjectNames(callback);
                        }
                    });
                });

                socket.on('getAllowedProjectNames', function(callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.getProjectNames(function(err,names){
                                if(!err){
                                    var allowedNames = [];
                                    var answerNeeded = names.length;
                                    var isProjectReadable = function(name,callback){
                                        options.authInfo(getSessionID(socket),name,function(err,authObj){
                                            if(!err){
                                                if(authObj && authObj.read === true){
                                                    allowedNames.push(name);
                                                }
                                            }
                                            callback(err);
                                        });
                                    };
                                    if(answerNeeded>0){
                                        for(var i=0;i<names.length;i++){
                                            isProjectReadable(names[i],function(err){
                                                if(--answerNeeded === 0){
                                                    callback(null,allowedNames);
                                                }
                                            });
                                        }
                                    } else {
                                        callback(null,allowedNames);
                                    }
                                } else {
                                    callback(err);
                                }
                            });
                        }
                    });
                });

                socket.on('getAuthorizationInfo', function(name,callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            options.authInfo(getSessionID(socket),name,callback);
                        }
                    });
                });

                socket.on('deleteProject', function(projectName,callback){
                    options.authorization(getSessionID(socket),projectName,'delete',function(err,cando){
                        if(err || !cando){
                            callback(err);
                        } else {
                            _database.deleteProject(projectName,function(err){
                                if(err){
                                    callback(err);
                                } else {
                                    //TODO what to do with the object itself???
                                    callback(null);
                                }
                            });
                        }
                    });
                });

                socket.on('openProject', function(projectName,callback){
                    checkDatabase(function(err){
                        if(err){
                            callback(err);
                        } else {
                            _database.getProjectNames(function(err,names){
                                if(names.indexOf(projectName) === -1){
                                    //project creation
                                    createProject(getSessionID(socket),projectName,callback);
                                } else {
                                    checkProject(getSessionID(socket),projectName,callback);
                                }
                            });
                        }
                    });
                });

                socket.on('closeProject', function(projectName,callback){
                    callback = callback || function() {};
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err) {
                            callback(err);
                        } else {
                            //TODO put this together
                            //var index = _references[projectName].indexOf(getSessionID(socket));
                            //_references[projectName].splice(index,1);
                            //if(_references[projectName].length === 0){
                                //delete _references[projectName];
                                //delete _projects[projectName];
                                //project.closeProject(callback);
                            //} else {
                                callback(null);
                           // }
                        }
                    });
                });

                socket.on('loadObject', function(projectName,hash,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.loadObject(hash,callback);
                        }
                    });
                });

                socket.on('insertObject', function(projectName,object,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            options.authorization(getSessionID(socket),projectName,'write',function(err,cando){
                               if(!err && cando === true){
                                   project.insertObject(object,callback);
                               } else {
                                   callback(err);
                               }
                            });
                        }
                    });
                });

                socket.on('findHash', function(projectName,beginning,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.findHash(beginning,callback);
                        }
                    });
                });

                socket.on('dumpObjects', function(projectName,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.dumpObjects(callback);
                        }
                    });
                });
                socket.on('getBranchNames', function(projectName,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.getBranchNames(callback);
                        }
                    });
                });
                socket.on('getBranchHash', function(projectName,branch,oldhash,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.getBranchHash(branch,oldhash,callback);
                        }
                    });
                });
                socket.on('setBranchHash', function(projectName,branch,oldhash,newhash,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            options.authorization(getSessionID(socket),projectName,'write',function(err,cando){
                                if(!err && cando === true){
                                    project.setBranchHash(branch,oldhash,newhash,callback);
                                } else {
                                    callback(err);
                                }
                            });
                        }
                    });
                });
                socket.on('getCommits',function(projectName,before,number,callback){
                    checkProject(getSessionID(socket),projectName,function(err,project){
                        if(err){
                            callback(err);
                        } else {
                            project.getCommits(before,number,callback);
                        }
                    });
                });

                //worker commands
                socket.on('simpleRequest',function(parameters,callback){
                    if(socket.handshake){
                        parameters.webGMESessionId = getSessionID(socket) || null;
                    }
                    _workerManager.request(parameters,callback);
                });

                socket.on('simpleResult',function(resultId,callback){
                    getWorkerResult(resultId,callback);
                });

                //token for REST
                socket.on('getToken',function(callback){
                    options.getToken(getSessionID(socket),callback);
                });

                socket.on('disconnect',function(){
                    //TODO temporary the disconnect function has been removed
                });
            });

            _workerManager = new SWM({
                basedir:options.basedir,
                mongoip:options.host,
                mongoport:options.port,
                mongodb:options.database,
                intoutdir:options.intoutdir,
                pluginBasePaths:options.pluginBasePaths,
                serverPort:options.webServerPort,
                sessionToUser:options.sessionToUser
            });
        }

        function close(){

            //disconnect clients
            if(_socket){
                //_socket.sockets.emit('disconnect');
                _socket.sockets.clients().forEach(function (socket){
                    socket.disconnect();
                });
                _socket.server.close();
                _socket = null;
            }

            if(_databaseOpened){
                //close projects
                for(var i in _projects){
                    _projects[i].closeProject(null);
                }

                //close database
                _database.closeDatabase(null);
            }

            _objects = {};
            _projects = {};
            //_references = {};
            _databaseOpened = false;
        }

        function getWorkerResult(resultId,callback){
            _workerManager.result(resultId,callback);
        }

        return {
            open: open,
            close: close,
            getWorkerResult: getWorkerResult
        };
    };

    return server;
});
<|endoftext|>