<commit_before>var path = require('path');

require.paths.unshift(path.join(__dirname, 'vendor'),
                      path.join(__dirname, 'journey'));

var sys = require("sys"),
   http = require("http"),
 events = require('events'),
     fs = require("fs"),
    url = require('url');

var querystring = require('querystring');

var journey = exports;

var BadRequest = function (msg) {
    this.status = 400;
    this.headers = {};
    this.body = { error: msg };
};
var NotFound = function (msg) {
    this.status = 404;
    this.headers = {};
    this.body = { error: msg };
};
var MethodNotAllowed = function (allowed) {
    this.status = 405;
    this.headers = { allow: allowed };
    this.body = { error: "method not allowed." };
};
var NotAcceptable = function (msg) {
    this.status = 406;
    this.headers = {};
    this.body = { error: msg, only: "application/json" };
};
var NotImplemented = function (msg) {
    this.status = 501;
    this.headers = {};
    this.body = { error: msg };
};

journey.env = 'development';
journey.version = [0, 1, 0];

//
// Logging & Debugging functions
//

journey.logger = {
    info: function (s) {
        if (journey.env === 'development') sys.puts(s);
    },

    err: function (s) {
        if (journey.env === 'development') sys.puts(s.stylize('red'));
    }
};
journey.log = journey.logger.info;
journey.debug = function (s) {
    sys.puts((s || 'false').toString().stylize('magenta'));
};

//
// The Router
//

journey.Router = function Router(routes) {
    var map = journey.map(this);

    map.__defineGetter__('root', function () {
        return this.get('/');
    });

    map.__defineGetter__('any', function () {
        return this.route(/(.*)/);
    });

    this.routes = [];

    // Call map() in the context of `this.map`, so `this`
    // can be used instead of the passed argument.
    routes.call(map, map);
};

journey.Router.methods = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'];

journey.map = function (context) {
    return {
        paths: [],

        get:  function (pattern, opts) { return this.route('GET',    pattern, opts) },
        put:  function (pattern, opts) { return this.route('PUT',    pattern, opts) },
        post: function (pattern, opts) { return this.route('POST',   pattern, opts) },
        del:  function (pattern, opts) { return this.route('DELETE', pattern, opts) },

        route: function (/* variable arguments */) {
            var route, args = Array.prototype.slice.call(arguments).filter(function (a) { return a }),
                // Defaults
                pattern     = this.paths.length ? '' : /.*/,
                ignoreCase  = false,
                method      = journey.Router.methods,
                constraints = {};

            args.forEach(function (arg) {
                if (journey.Router.methods.indexOf(arg) !== -1 || Array.isArray(arg)) {
                    method = arg;
                } else if (typeof(arg) === "object") {
                    constraints = arg;
                } else if (typeof(arg) === "string" || arg.exec) {
                    pattern = arg;
                } else {
                    throw new(Error)("cannot understand route.");
                }
            });

            if (typeof(pattern) !== "string") {
                // If we're in a nested path, '/i' doesn't mean much,
                // as we concatinate strings and regexps.
                ignoreCase = this.paths.length || pattern.ignoreCase;
                pattern = pattern.source;
            }

            // Trim trailing and duplicate slashes and add ^$ markers
            pattern = '^' + this.paths.concat([pattern]).join('/')
                                      .match(/^\^?(?:(\/)|\/?(.*?)\/?)\$?$/)
                                      .slice(1).join('')
                                      .replace(/\/+/g, '/') + '$';

            pattern = new(RegExp)(pattern, ignoreCase ? 'i' : '');

            context.routes.push(route = {
                pattern: pattern,
                method: method,
                constraints: constraints
            });

            return {
                bind: function (handler) {
                    route.handler = handler;
                    return route;
                }
            };
        },
        path: function (pattern, map) {
            this.paths.push(pattern);
            map.call(this, this);
            this.paths.pop();
        },
        trail: function (from, to) {
            // Logging
        }
    };
};

journey.Router.prototype = {

    // Called when the HTTP request is 'complete'
    // and ready to be processed.
    route: function (request, body, callback) {
        var promise = new(events.EventEmitter);
        var that = this;

        request.url = url.parse(request.url);

        // Call the router asynchronously, so we can return a promise
        process.nextTick(function () {
            // Dispatch the HTTP request:
            // As the last argument, we send the function to be called when the response is ready
            // to be sent back to the client -- this allows us to keep our entry and exit point
            // in the same spot. `outcome` is an object with a `status`, a `body` and `headers`
            that.dispatch(request, body || "", function (outcome) {
                outcome.headers["Content-Type"] = "application/json";
                outcome.headers["Date"] = new(Date)().toUTCString();
                outcome.headers["Server"] = "journey/" + journey.version.join('.');

                if (outcome.body) {
                    if (typeof(outcome.body) !== 'string') {
                        outcome.body = JSON.stringify(outcome.body);
                    }
                    outcome.body += '\r\n';

                    if (outcome.status >= 300) {
                        outcome.headers['Content-Length'] = outcome.body.length.toString();
                    }
                }

                if (callback) { callback(outcome) }
                else          { promise.emit("success", outcome) }

                promise.emit("log", new(Date)().toUTCString() +
                             " -- " + request.method +  " "   +
                             request.url.href + " - HTTP " + outcome.status);
            });
        });
        return promise;
    },

    constraints: {
        //
        // Check if the request has a non-empty body
        //
        payload: function (payload, request, body) {
            return Boolean(body) === payload;
        },

        //
        // Run a function, and check return value
        //
        assert: function (assert, request, body) {
            return Boolean(assert(request, body));
        }
    },

    resolve: function (request, body) {
        var that = this, allowedMethods = [];
        //
        // Return the first matching route
        //
        var found = find(this.routes, function (route) {
            // Match the pattern with the url
            var match = (function (pattern) {
                var path = request.url.pathname;

                if (! path) { throw new(BadRequest) }

                return (path.length > 1 ? path.slice(1) : path).match(pattern);
            })(route.pattern);

            //
            // Run through the specified constraints,
            // making sure everything passes.
            //
            var constraints = Object.keys(route.constraints).length === 0 ? true :
                Object.keys(route.constraints).every(function (key) {
                // Check if the constraint has been defined, then run it.
                if (key in that.constraints) {
                    return that.constraints[key](route.constraints[key], request, body);
                } else {
                    throw new(Error)("constraint '" + key + "' not found.");
                }
            });

            if (match && constraints) {
                if (! ('handler' in route)) { throw new(NotImplemented)("unbound route") }
                if ((Array.isArray(route.method) && route.method.indexOf(request.method) !== -1) ||
                    (route.method === request.method) || !route.method) {
                    return function (res, params) {
                        return route.handler.apply(this, [res].concat(match.slice(1), params));
                    };
                } else {
                    if (allowedMethods.indexOf(route.method) === -1) {
                        allowedMethods.push(route.method);
                    }
                    return false;
                }
            }
            return false;
        });

        if (found) {
            return found;
        } else if (allowedMethods.length) {
            throw new(MethodNotAllowed)(allowedMethods.join(','));
        } else {
            return false;
        }
    },

    // This function glues together the request resolver, with the responder.
    // It creates a new `route` context, in which the response will be generated.
    dispatch: function (request, body, respond) {
        var resolved, route, parser,
            params = querystring.parse(request.url.query),
            accepts = request.headers.accept;

        accepts = accepts && accepts.split(/[,;] */);

        // Journey being a JSON-only server, we expect the 'Accept' header
        // to be set accordingly.
        if (accepts && accepts.indexOf("application/json") === -1 &&
                       accepts.indexOf("*/*") === -1) {
            return respond(new(NotAcceptable)(
                "cannot generate '" + request.headers.accept + "' response")
            );
        }

        try {
            resolved = this.resolve(request, body);
        } catch (e) {
            if (e.status) { // If it's an HTTP Error
                return respond({
                    headers: e.headers || {},
                    status: e.status,
                    body: JSON.stringify(e.body)
                });
            } else {
                throw e;
            }
        }

        route = this.draw(request, respond);

        if (resolved) {
            if (body) {
                parser = request.headers["content-type"] === "application/json" ? JSON.parse
                                                                                : querystring.parse;
                try {
                    mixin(params, parser(body));
                } catch (e) {
                    return respond(new(BadRequest)("malformed data"));
                }
            }
            return route.go(resolved, params);
        } else {
            return respond(new(NotFound)("request not found"));
        }
    },

    // A constructor of sorts, which returns a 'Routing context', in which the response
    // status is evaluated.
    draw: function (req, respond) {
        return {
            request: req,
            respond: respond,
            baseResponse: {
                status: req.method == 'POST' ? 201 : 200,
                body: "",
                headers: {"Content-Type" : "application/json"}
            },

            // A wrapper around `respond()`, it allows us to respond in a variety of
            // ways, such as: `201`, `"Hello World"`, `[201, "Hello", {'Content-Type':'text/html'}]`, etc.
            // All parameters are optional.
            responder: function (response) {
                // If more than one argument was received, treat it as if it was an array.
                if (arguments.length > 1) { response = Array.prototype.slice.apply(arguments) }

                this.respond((function (baseResponse) {
                    switch (typeOf(response)) {
                        case "object":
                            return mixin({}, baseResponse, { body: response });
                        case "string":
                            return mixin({}, baseResponse, { body: { journey: response } });
                        case "number":
                            return mixin({}, baseResponse, { status: response });
                        case "array":
                            if (response.length === 3) {
                                return {
                                    status:  response[0],
                                    headers: response[1],
                                    body:    response[2]
                                };
                            } else {
                                throw new(Error)("expected 3 elements in response");
                            }
                        default:
                            throw new(Error)("wrong response type");
                    }
                })(this.baseResponse));
            },

            sendBody: function (body) {
                this.responder({ body: body });
            },

            sendHeaders: function (status, headers) {
                this.responder({ status: status, headers: headers });
            },

            go: function (destination, params) {
                this.send = this.responder;

                try {
                    destination.call(this, this, params) || {};
                } catch (err) {
                    journey.logger.err(err.stack || err.toString() + "\n");
                    this.respond({
                        body: { error: err.message || err,
                        stack: err.stack && err.stack.split('\n') },
                        status: err.status || 500, headers: {}
                    });
                }
            }
        }
    }
};

//
// Utility functions
//
function typeOf(value) {
    var s = typeof(value),
        types = [Object, String, RegExp, Number, Function, Boolean, Date];

    if (Array.isArray(value)) {
        return 'array';
    } else if (s === 'object' || s === 'function') {
        if (value) {
            types.forEach(function (t) {
                if (value instanceof t) { s = t.name.toLowerCase() }
            });
        } else { s = 'null' }
    }
    return s;
}
function mixin(target) {
    var args = Array.prototype.slice.call(arguments, 1);

    args.forEach(function (a) {
        var keys = Object.keys(a);
        for (var i = 0; i < keys.length; i++) {
            target[keys[i]] = a[keys[i]];
        }
    });
    return target;
};
function find(array, fun) {
    for (var i = 0; i < array.length; i++) {
        if (ret = fun(array[i])) return ret;
    }
    return false;
};
<commit_msg>throw error if non-string passed to path()<commit_after>var path = require('path');

require.paths.unshift(path.join(__dirname, 'vendor'),
                      path.join(__dirname, 'journey'));

var sys = require("sys"),
   http = require("http"),
 events = require('events'),
     fs = require("fs"),
    url = require('url');

var querystring = require('querystring');

var journey = exports;

var BadRequest = function (msg) {
    this.status = 400;
    this.headers = {};
    this.body = { error: msg };
};
var NotFound = function (msg) {
    this.status = 404;
    this.headers = {};
    this.body = { error: msg };
};
var MethodNotAllowed = function (allowed) {
    this.status = 405;
    this.headers = { allow: allowed };
    this.body = { error: "method not allowed." };
};
var NotAcceptable = function (msg) {
    this.status = 406;
    this.headers = {};
    this.body = { error: msg, only: "application/json" };
};
var NotImplemented = function (msg) {
    this.status = 501;
    this.headers = {};
    this.body = { error: msg };
};

journey.env = 'development';
journey.version = [0, 1, 0];

//
// Logging & Debugging functions
//

journey.logger = {
    info: function (s) {
        if (journey.env === 'development') sys.puts(s);
    },

    err: function (s) {
        if (journey.env === 'development') sys.puts(s.stylize('red'));
    }
};
journey.log = journey.logger.info;
journey.debug = function (s) {
    sys.puts((s || 'false').toString().stylize('magenta'));
};

//
// The Router
//

journey.Router = function Router(routes) {
    var map = journey.map(this);

    map.__defineGetter__('root', function () {
        return this.get('/');
    });

    map.__defineGetter__('any', function () {
        return this.route(/(.*)/);
    });

    this.routes = [];

    // Call map() in the context of `this.map`, so `this`
    // can be used instead of the passed argument.
    routes.call(map, map);
};

journey.Router.methods = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'];

journey.map = function (context) {
    return {
        paths: [],

        get:  function (pattern, opts) { return this.route('GET',    pattern, opts) },
        put:  function (pattern, opts) { return this.route('PUT',    pattern, opts) },
        post: function (pattern, opts) { return this.route('POST',   pattern, opts) },
        del:  function (pattern, opts) { return this.route('DELETE', pattern, opts) },

        route: function (/* variable arguments */) {
            var route, args = Array.prototype.slice.call(arguments).filter(function (a) { return a }),
                // Defaults
                pattern     = this.paths.length ? '' : /.*/,
                ignoreCase  = false,
                method      = journey.Router.methods,
                constraints = {};

            args.forEach(function (arg) {
                if (journey.Router.methods.indexOf(arg) !== -1 || Array.isArray(arg)) {
                    method = arg;
                } else if (typeof(arg) === "object") {
                    constraints = arg;
                } else if (typeof(arg) === "string" || arg.exec) {
                    pattern = arg;
                } else {
                    throw new(Error)("cannot understand route.");
                }
            });

            if (typeof(pattern) !== "string") {
                // If we're in a nested path, '/i' doesn't mean much,
                // as we concatinate strings and regexps.
                ignoreCase = this.paths.length || pattern.ignoreCase;
                pattern = pattern.source;
            }

            // Trim trailing and duplicate slashes and add ^$ markers
            pattern = '^' + this.paths.concat([pattern]).join('/')
                                      .match(/^\^?(?:(\/)|\/?(.*?)\/?)\$?$/)
                                      .slice(1).join('')
                                      .replace(/\/+/g, '/') + '$';

            pattern = new(RegExp)(pattern, ignoreCase ? 'i' : '');

            context.routes.push(route = {
                pattern: pattern,
                method: method,
                constraints: constraints
            });

            return {
                bind: function (handler) {
                    route.handler = handler;
                    return route;
                }
            };
        },
        path: function (pattern, map) {
            if (typeof(pattern) !== 'string') {
                throw new(TypeError)('path only accepts strings patterns.');
            }
            this.paths.push(pattern);
            map.call(this, this);
            this.paths.pop();
        },
        trail: function (from, to) {
            // Logging
        }
    };
};

journey.Router.prototype = {

    // Called when the HTTP request is 'complete'
    // and ready to be processed.
    route: function (request, body, callback) {
        var promise = new(events.EventEmitter);
        var that = this;

        request.url = url.parse(request.url);

        // Call the router asynchronously, so we can return a promise
        process.nextTick(function () {
            // Dispatch the HTTP request:
            // As the last argument, we send the function to be called when the response is ready
            // to be sent back to the client -- this allows us to keep our entry and exit point
            // in the same spot. `outcome` is an object with a `status`, a `body` and `headers`
            that.dispatch(request, body || "", function (outcome) {
                outcome.headers["Content-Type"] = "application/json";
                outcome.headers["Date"] = new(Date)().toUTCString();
                outcome.headers["Server"] = "journey/" + journey.version.join('.');

                if (outcome.body) {
                    if (typeof(outcome.body) !== 'string') {
                        outcome.body = JSON.stringify(outcome.body);
                    }
                    outcome.body += '\r\n';

                    if (outcome.status >= 300) {
                        outcome.headers['Content-Length'] = outcome.body.length.toString();
                    }
                }

                if (callback) { callback(outcome) }
                else          { promise.emit("success", outcome) }

                promise.emit("log", new(Date)().toUTCString() +
                             " -- " + request.method +  " "   +
                             request.url.href + " - HTTP " + outcome.status);
            });
        });
        return promise;
    },

    constraints: {
        //
        // Check if the request has a non-empty body
        //
        payload: function (payload, request, body) {
            return Boolean(body) === payload;
        },

        //
        // Run a function, and check return value
        //
        assert: function (assert, request, body) {
            return Boolean(assert(request, body));
        }
    },

    resolve: function (request, body) {
        var that = this, allowedMethods = [];
        //
        // Return the first matching route
        //
        var found = find(this.routes, function (route) {
            // Match the pattern with the url
            var match = (function (pattern) {
                var path = request.url.pathname;

                if (! path) { throw new(BadRequest) }

                return (path.length > 1 ? path.slice(1) : path).match(pattern);
            })(route.pattern);

            //
            // Run through the specified constraints,
            // making sure everything passes.
            //
            var constraints = Object.keys(route.constraints).length === 0 ? true :
                Object.keys(route.constraints).every(function (key) {
                // Check if the constraint has been defined, then run it.
                if (key in that.constraints) {
                    return that.constraints[key](route.constraints[key], request, body);
                } else {
                    throw new(Error)("constraint '" + key + "' not found.");
                }
            });

            if (match && constraints) {
                if (! ('handler' in route)) { throw new(NotImplemented)("unbound route") }
                if ((Array.isArray(route.method) && route.method.indexOf(request.method) !== -1) ||
                    (route.method === request.method) || !route.method) {
                    return function (res, params) {
                        return route.handler.apply(this, [res].concat(match.slice(1), params));
                    };
                } else {
                    if (allowedMethods.indexOf(route.method) === -1) {
                        allowedMethods.push(route.method);
                    }
                    return false;
                }
            }
            return false;
        });

        if (found) {
            return found;
        } else if (allowedMethods.length) {
            throw new(MethodNotAllowed)(allowedMethods.join(','));
        } else {
            return false;
        }
    },

    // This function glues together the request resolver, with the responder.
    // It creates a new `route` context, in which the response will be generated.
    dispatch: function (request, body, respond) {
        var resolved, route, parser,
            params = querystring.parse(request.url.query),
            accepts = request.headers.accept;

        accepts = accepts && accepts.split(/[,;] */);

        // Journey being a JSON-only server, we expect the 'Accept' header
        // to be set accordingly.
        if (accepts && accepts.indexOf("application/json") === -1 &&
                       accepts.indexOf("*/*") === -1) {
            return respond(new(NotAcceptable)(
                "cannot generate '" + request.headers.accept + "' response")
            );
        }

        try {
            resolved = this.resolve(request, body);
        } catch (e) {
            if (e.status) { // If it's an HTTP Error
                return respond({
                    headers: e.headers || {},
                    status: e.status,
                    body: JSON.stringify(e.body)
                });
            } else {
                throw e;
            }
        }

        route = this.draw(request, respond);

        if (resolved) {
            if (body) {
                parser = request.headers["content-type"] === "application/json" ? JSON.parse
                                                                                : querystring.parse;
                try {
                    mixin(params, parser(body));
                } catch (e) {
                    return respond(new(BadRequest)("malformed data"));
                }
            }
            return route.go(resolved, params);
        } else {
            return respond(new(NotFound)("request not found"));
        }
    },

    // A constructor of sorts, which returns a 'Routing context', in which the response
    // status is evaluated.
    draw: function (req, respond) {
        return {
            request: req,
            respond: respond,
            baseResponse: {
                status: req.method == 'POST' ? 201 : 200,
                body: "",
                headers: {"Content-Type" : "application/json"}
            },

            // A wrapper around `respond()`, it allows us to respond in a variety of
            // ways, such as: `201`, `"Hello World"`, `[201, "Hello", {'Content-Type':'text/html'}]`, etc.
            // All parameters are optional.
            responder: function (response) {
                // If more than one argument was received, treat it as if it was an array.
                if (arguments.length > 1) { response = Array.prototype.slice.apply(arguments) }

                this.respond((function (baseResponse) {
                    switch (typeOf(response)) {
                        case "object":
                            return mixin({}, baseResponse, { body: response });
                        case "string":
                            return mixin({}, baseResponse, { body: { journey: response } });
                        case "number":
                            return mixin({}, baseResponse, { status: response });
                        case "array":
                            if (response.length === 3) {
                                return {
                                    status:  response[0],
                                    headers: response[1],
                                    body:    response[2]
                                };
                            } else {
                                throw new(Error)("expected 3 elements in response");
                            }
                        default:
                            throw new(Error)("wrong response type");
                    }
                })(this.baseResponse));
            },

            sendBody: function (body) {
                this.responder({ body: body });
            },

            sendHeaders: function (status, headers) {
                this.responder({ status: status, headers: headers });
            },

            go: function (destination, params) {
                this.send = this.responder;

                try {
                    destination.call(this, this, params) || {};
                } catch (err) {
                    journey.logger.err(err.stack || err.toString() + "\n");
                    this.respond({
                        body: { error: err.message || err,
                        stack: err.stack && err.stack.split('\n') },
                        status: err.status || 500, headers: {}
                    });
                }
            }
        }
    }
};

//
// Utility functions
//
function typeOf(value) {
    var s = typeof(value),
        types = [Object, String, RegExp, Number, Function, Boolean, Date];

    if (Array.isArray(value)) {
        return 'array';
    } else if (s === 'object' || s === 'function') {
        if (value) {
            types.forEach(function (t) {
                if (value instanceof t) { s = t.name.toLowerCase() }
            });
        } else { s = 'null' }
    }
    return s;
}
function mixin(target) {
    var args = Array.prototype.slice.call(arguments, 1);

    args.forEach(function (a) {
        var keys = Object.keys(a);
        for (var i = 0; i < keys.length; i++) {
            target[keys[i]] = a[keys[i]];
        }
    });
    return target;
};
function find(array, fun) {
    for (var i = 0; i < array.length; i++) {
        if (ret = fun(array[i])) return ret;
    }
    return false;
};
<|endoftext|>


<commit_before>'use strict';

/** Load other modules. */
var _ = require('lodash-compat'),
    mapping = require('./mapping.js'),
    util = require('./util.js');

/** Native method references. */
var push = Array.prototype.push;

/*----------------------------------------------------------------------------*/

/** List of all object property dependencies. */
exports.objDeps = _.uniq(_.transform(mapping.objDep, _.bind(push.apply, push), [])).sort();

/** List of all variable dependencies. */
exports.varDeps = _.uniq(_.transform(mapping.varDep, _.bind(push.apply, push), [])).sort();

/** List of all functions. */
exports.funcs = _.filter(_.difference(_.keys(mapping.funcDep), exports.objDeps, exports.varDeps).sort(), function(key) {
  var type = typeof _.prototype[key];
  return type == 'function' || type == 'undefined';
});

/** List of lodash functions included by default. */
exports.includes = _.intersection(exports.funcs, _.union(
  _.functions(_),
  _.functions(_.prototype),
  mapping.category.Chain,
  ['main']
));

_.assign(module.exports, {

  /** List of all function categories. */
  'categories': _.keys(mapping.category).sort(),

  /** List of variables with complex assignments. */
  'complexVars': [
    'cloneableTags',
    'contextProps',
    'ctorByTag',
    'freeGlobal',
    'nonEnumProps',
    'reWords',
    'shadowProps',
    'support',
    'typedArrayTags',
    'whitespace'
  ],

  /** List of the default ways to export the `lodash` function. */
  'exports': [
    'amd',
    'commonjs',
    'global',
    'iojs',
    'node',
    'umd'
  ],

  /** List of dependencies that should not cause a minor bump when changed. */
  'laxSemVerDeps': [
    'isBoolean',
    'isError',
    'isFinite',
    'isFunction',
    'isNaN',
    'isNull',
    'isNumber',
    'isObject',
    'isObjectLike',
    'isString',
    'isUndefined'
  ],

  /** List of functions that support argument placeholders. */
  'placeholderFuncs': [
    'bind',
    'bindKey',
    'curry',
    'curryRight',
    'partial',
    'partialRight'
  ],

  /* Used to designate dependencies at the top level. */
  'topLevelDeps': [
    'main',
    'support'
  ],

  /** List of uninlinable dependencies. */
  'uninlinables': _.union(
    _.without(exports.includes,
      'constant',
      'drop',
      'dropRight',
      'escapeRegExp',
      'filter',
      'identity',
      'isObject',
      'matches',
      'noop',
      'now',
      'pluck',
      'property',
      'values'
    ),
    _.keys(_.support),
    _.keys(_.templateSettings), [
    'arrayCopy',
    'arrayEach',
    'arrayEvery',
    'arrayFilter',
    'arrayMap',
    'arrayMax',
    'arrayMin',
    'baseAssign',
    'baseAt',
    'baseCallback',
    'baseClone',
    'baseCompareAscending',
    'baseCopy',
    'baseCreate',
    'baseDelay',
    'baseDifference',
    'baseEach',
    'baseEachRight',
    'baseFilter',
    'baseFind',
    'baseFindIndex',
    'baseFlatten',
    'baseFor',
    'baseForRight',
    'baseFunctions',
    'baseGet',
    'baseIndexOf',
    'baseIsEqual',
    'baseIsMatch',
    'baseMatches',
    'baseMatchesProperty',
    'baseRandom',
    'baseReduce',
    'baseSlice',
    'baseSortBy',
    'baseSortByOrder',
    'baseToString',
    'baseUniq',
    'baseValues',
    'binaryIndex',
    'binaryIndexBy',
    'bindCallback',
    'cacheIndexOf',
    'charsLeftIndex',
    'charsRightIndex',
    'createAggregator',
    'createAssigner',
    'createCache',
    'createCompounder',
    'createPadding',
    'createWrapper',
    'isIterateeCall',
    'pickByArray',
    'pickByCallback',
    'reInterpolate',
    'reEscape',
    'reEvaluate',
    'replaceHolders',
    'templateSettings',
    'toIterable',
    'toPath',
    'trimmedLeftIndex',
    'trimmedRightIndex'
  ]).sort()
});
<commit_msg>Make `_.last` inlinable.<commit_after>'use strict';

/** Load other modules. */
var _ = require('lodash-compat'),
    mapping = require('./mapping.js'),
    util = require('./util.js');

/** Native method references. */
var push = Array.prototype.push;

/*----------------------------------------------------------------------------*/

/** List of all object property dependencies. */
exports.objDeps = _.uniq(_.transform(mapping.objDep, _.bind(push.apply, push), [])).sort();

/** List of all variable dependencies. */
exports.varDeps = _.uniq(_.transform(mapping.varDep, _.bind(push.apply, push), [])).sort();

/** List of all functions. */
exports.funcs = _.filter(_.difference(_.keys(mapping.funcDep), exports.objDeps, exports.varDeps).sort(), function(key) {
  var type = typeof _.prototype[key];
  return type == 'function' || type == 'undefined';
});

/** List of lodash functions included by default. */
exports.includes = _.intersection(exports.funcs, _.union(
  _.functions(_),
  _.functions(_.prototype),
  mapping.category.Chain,
  ['main']
));

_.assign(module.exports, {

  /** List of all function categories. */
  'categories': _.keys(mapping.category).sort(),

  /** List of variables with complex assignments. */
  'complexVars': [
    'cloneableTags',
    'contextProps',
    'ctorByTag',
    'freeGlobal',
    'nonEnumProps',
    'reWords',
    'shadowProps',
    'support',
    'typedArrayTags',
    'whitespace'
  ],

  /** List of the default ways to export the `lodash` function. */
  'exports': [
    'amd',
    'commonjs',
    'global',
    'iojs',
    'node',
    'umd'
  ],

  /** List of dependencies that should not cause a minor bump when changed. */
  'laxSemVerDeps': [
    'isBoolean',
    'isError',
    'isFinite',
    'isFunction',
    'isNaN',
    'isNull',
    'isNumber',
    'isObject',
    'isObjectLike',
    'isString',
    'isUndefined'
  ],

  /** List of functions that support argument placeholders. */
  'placeholderFuncs': [
    'bind',
    'bindKey',
    'curry',
    'curryRight',
    'partial',
    'partialRight'
  ],

  /* Used to designate dependencies at the top level. */
  'topLevelDeps': [
    'main',
    'support'
  ],

  /** List of uninlinable dependencies. */
  'uninlinables': _.union(
    _.without(exports.includes,
      'constant',
      'drop',
      'dropRight',
      'escapeRegExp',
      'filter',
      'identity',
      'isObject',
      'last',
      'matches',
      'noop',
      'now',
      'pluck',
      'property',
      'values'
    ),
    _.keys(_.support),
    _.keys(_.templateSettings), [
    'arrayCopy',
    'arrayEach',
    'arrayEvery',
    'arrayFilter',
    'arrayMap',
    'arrayMax',
    'arrayMin',
    'baseAssign',
    'baseAt',
    'baseCallback',
    'baseClone',
    'baseCompareAscending',
    'baseCopy',
    'baseCreate',
    'baseDelay',
    'baseDifference',
    'baseEach',
    'baseEachRight',
    'baseFilter',
    'baseFind',
    'baseFindIndex',
    'baseFlatten',
    'baseFor',
    'baseForRight',
    'baseFunctions',
    'baseGet',
    'baseIndexOf',
    'baseIsEqual',
    'baseIsMatch',
    'baseMatches',
    'baseMatchesProperty',
    'baseRandom',
    'baseReduce',
    'baseSlice',
    'baseSortBy',
    'baseSortByOrder',
    'baseToString',
    'baseUniq',
    'baseValues',
    'binaryIndex',
    'binaryIndexBy',
    'bindCallback',
    'cacheIndexOf',
    'charsLeftIndex',
    'charsRightIndex',
    'createAggregator',
    'createAssigner',
    'createCache',
    'createCompounder',
    'createPadding',
    'createWrapper',
    'isIterateeCall',
    'pickByArray',
    'pickByCallback',
    'reInterpolate',
    'reEscape',
    'reEvaluate',
    'replaceHolders',
    'templateSettings',
    'toIterable',
    'toPath',
    'trimmedLeftIndex',
    'trimmedRightIndex'
  ]).sort()
});
<|endoftext|>


<commit_before>var through = require('through2')
var pump = require('pump')
var allContainers = require('docker-allcontainers')
var parser = require('./parser')

function loghose (opts) {
  opts = opts || {}
  var result = through.obj()
  var events = opts.events || allContainers(opts)
  var streams = {}
  var oldDestroy = result.destroy

  result.setMaxListeners(0)

  result.destroy = function () {
    Object.keys(streams).forEach(detachContainer)
    events.destroy()
    oldDestroy.call(this)
  }

  events.on('start', attachContainer)
  events.on('stop', function (meta) {
    detachContainer(meta.id)
  })

  function detachContainer (id) {
    if (streams[id]) {
      streams[id].destroy()
      delete streams[id]
    }
  }

  // exposing detachContainer function
  result.detachContainer = detachContainer.bind(this)
  return result

  function attachContainer (data, container) {
    // we are trying to tap into this container
    // we should not do that, or we might be stuck in
    // an output loop
    if (!opts.includeCurrentContainer && data.id.indexOf(process.env.HOSTNAME) === 0) {
      return
    }

    container.inspect(function (err, info) {
      if (err) {
        // container might not exists anymore ...
        if (/no such container/i.test(err.toString())) {
          // ignore this container and don't try to attach
          return
        } else {
          // any other error should be submitted to result stream
          // TODO catch specific TCP/HTTP errors e.g. indicating lost of connection/timeouts to dockerd
          return result.emit('error', err)
        }
      }
      // optional attachFilter decides to attach to container or not
      if (opts.attachFilter &&
          typeof opts.attachFilter === 'function' &&
          !opts.attachFilter(data.id, info)) {
        return
      }
      container.attach({stream: true, stdout: true, stderr: true}, function (err, stream) {
        if (err) {
           // no stream availaable
          return
        }
        opts.tty = info.Config.Tty
        streams[data.id] = stream
        pump(
          stream,
          parser(data, opts)
        ).pipe(result, {end: false}).on('error', function () {
          /* continue, let's wait for docker restart */
        })
      })
    })
  }
}

module.exports = loghose
<commit_msg>format<commit_after>var through = require('through2')
var pump = require('pump')
var allContainers = require('docker-allcontainers')
var parser = require('./parser')

function loghose (opts) {
  opts = opts || {}
  var result = through.obj()
  var events = opts.events || allContainers(opts)
  var streams = {}
  var oldDestroy = result.destroy

  result.setMaxListeners(0)

  result.destroy = function () {
    Object.keys(streams).forEach(detachContainer)
    events.destroy()
    oldDestroy.call(this)
  }

  events.on('start', attachContainer)
  events.on('stop', function (meta) {
    detachContainer(meta.id)
  })

  function detachContainer (id) {
    if (streams[id]) {
      streams[id].destroy()
      delete streams[id]
    }
  }

  // exposing detachContainer function
  result.detachContainer = detachContainer.bind(this)
  return result

  function attachContainer (data, container) {
    // we are trying to tap into this container
    // we should not do that, or we might be stuck in
    // an output loop
    if (!opts.includeCurrentContainer && data.id.indexOf(process.env.HOSTNAME) === 0) {
      return
    }

    container.inspect(function (err, info) {
      if (err) {
        // container might not exists anymore ...
        if (/no such container/i.test(err.toString())) {
          // ignore this container and don't try to attach
          return
        } else {
          // any other error should be submitted to result stream
          // TODO catch specific TCP/HTTP errors e.g. indicating lost of connection/timeouts to dockerd
          return result.emit('error', err)
        }
      }
      // optional attachFilter decides to attach to container or not
      if (opts.attachFilter &&
          typeof opts.attachFilter === 'function' &&
          !opts.attachFilter(data.id, info)) {
        return
      }
      container.attach({ stream: true, stdout: true, stderr: true }, function (err, stream) {
        if (err) {
          // no stream availaable
          return
        }
        opts.tty = info.Config.Tty
        streams[data.id] = stream
        pump(
          stream,
          parser(data, opts)
        ).pipe(result, { end: false }).on('error', function () {
          /* continue, let's wait for docker restart */
        })
      })
    })
  }
}

module.exports = loghose
<|endoftext|>


<commit_before>var Bookshelf = require('bookshelf');
var hooker    = require('hooker');
var path      = require('path');
var Promise   = require('bluebird');

var Manager = function(root, bookshelf) {
  if (!root) {
    throw new Error('Manager requires a path to model directory');
  }

  this.root = path.normalize(root);

  if (bookshelf) {
    this.initialize(bookshelf);
  } else {
    hooker.hook(Bookshelf, 'initialize', {
      once: true,
      post: this.initialize.bind(this)
    });
  }
};

Manager.manage = function(model) {
  if (!Manager.manages(model)) {
    Manager._managed.push(model);
  }

  return model;
};

Manager.manages = function(model) {
  if (!model instanceof Function) {
    return false;
  }

  return Manager._managed.indexOf(model) !== -1
};

Manager._managed = [];

Manager.prototype.initialize = function(bookshelf) {
  this.bookshelf  = bookshelf;
  this.knex       = this.bookshelf.knex;
  this.schema     = this.knex.schema;

  bookshelf.plugin('registry');

  hooker.hook(bookshelf, ['collection', 'model'], function(name, value) {
    if (!value) {
      return hooker.preempt(this.get(name));
    }
  }.bind(this));

  return this;
};

Manager.prototype._cache = {};

Manager.prototype.create = function(name, properties) {
  var Model = this.get(name);
  var model = new Model();

  return this.save(model, properties).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.debug = function(debug) {
  var level = 1;
  var methods = [
    'create',
    'fetch',
    'forge',
    'get',
    'load',
    'save',
    'saveCollection',
    'saveModel',
    'set',
    'setBelongsTo',
    'setBelongsToMany',
    'setCollection',
    'setHasMany',
    'setModel',
    'setScalar',
  ];

  var pre = function(name) {
    var indent  = new Array(level++).join('  ');
    var sliced  = Array.prototype.slice.call(arguments, 1);
    var args    = sliced.map(function(arg) {
      if (this.isCollection(arg)) {
        return '[Collection] (' + arg.length + ')';
      }

      if (this.isModel(arg)) {
        return '[Model `' + arg.tableName + '@' + arg.id + '`]';
      }

      return (JSON.stringify(arg) || 'null').split('\n').join('\n' + indent + '   ');
    }.bind(this)).join(',\n' + indent + '   ');

    console.log(indent, '<' + name + '>', '\n' + indent + '  ', args);
  };

  var post = function(result, name) {
    if (result && result.then) {
      result.then(function() {
        console.log(new Array(--level).join('  '), '</' + name + '>');

        return arguments[0];
      });
    };
  };

  if (typeof debug === 'undefined') {
    debug = true;
  }

  if (debug) {
    hooker.hook(this, methods, {
      passName: true,
      pre:      pre,
      post:     post
    });
  } else {
    hooker.unhook(this, methods);
  }

  return this;
};

Manager.prototype.fetch = function(name, properties, related) {
  var model = this.forge(name, properties);

  return model.fetch({
    withRelated: related,
  });
};

Manager.prototype.findRelated = function(properties, paths) {
  var related = [];

  properties  = properties || {};
  paths       = paths || [];

  for (var key in properties) {
    var value = properties[key];
    var ctor  = value ? value.constructor : null;

    if (ctor === Array) {
      related.push(paths.concat([key]).join('.'));

      if (value.length) {
        related = related.concat(this.findRelated(value[0], paths.concat([key])));
      }
    }

    if (ctor === Object) {
      related.push(paths.concat([key]).join('.'));

      related = related.concat(this.findRelated(value, paths.concat([key])));
    }
  }

  return related;
};

Manager.prototype.forge = function(name, properties) {
  var Model = this.get(name);

  // Model may already be instantiated
  if (Model instanceof this.bookshelf.Model) {
    Model = Model.constructor;
  }

  return Model.forge(properties);
};

Manager.prototype.get = function(Model) {
  if (!this.bookshelf) {
    throw new Error('Manager has not been initialized with instance of Bookshelf');
  }

  var name;

  if (typeof Model === 'string') {
    name = Model;

    if (this._cache[name]) {
      return this._cache[name];
    }

    var file = path.join(this.root, name);

    try {
      Model = require(file);
    } catch (e) {
      throw new Error('Could not find module `' + name + '` at `' + file + '.js`');
    }
  }

  if (Manager.manages(Model)) {
    Model = Model(this.bookshelf);
  }

  if (!this.isModel(Model) && !this.isCollection(Model)) {
    throw new Error('Expected a String, Model, Collection, or a Managed Model/Collection, got: ' + typeof Model);
  }

  if (this.isCollection(Model) && typeof Model.prototype.model === 'string') {
    Model.prototype.model = this.get(Model.prototype.model);
  }

  if (name) {
    if (this.isModel(Model)) {
      this._cache[name] = this.bookshelf.model(name, Model);
    } else if (this.isCollection(Model)) {
      this._cache[name] = this.bookshelf.collection(name, Model);
    }
  }

  return Model;
};

Manager.prototype.isModel = function(model) {
  if (!model || this.isCollection(model)) {
    return false;
  }

  return model instanceof this.bookshelf.Model || model.prototype instanceof this.bookshelf.Model;
};

Manager.prototype.isCollection = function(model) {
  if (!model) {
    return false;
  }

  return model instanceof this.bookshelf.Collection || model.prototype instanceof this.bookshelf.Collection;
};

Manager.prototype.save = function(model, properties) {
  if (this.isModel(model)) {
    return this.saveModel(model, properties);
  } else if (this.isCollection(model)) {
    return this.saveCollection(model, properties);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.saveCollection = function(collection, models) {
  return collection.mapThen(function(model) {
    return (model.isNew() || model.hasChanged()) ? model.save() : model;
  }).then(function() {
    return this.setCollection(collection, models);
  }.bind(this)).then(function(targets) {
    return targets.mapThen(function(target) {
      collection.add(target);

      return (target.isNew() || target.hasChanged()) ? target.save() : target;
    });
  }).then(function() {
    return collection;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.saveModel = function(model, properties) {
  return this.setModel(model, properties).then(function(result) {
    return (result.isNew() || result.hasChanged()) ? result.save() : result;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
}

Manager.prototype.set = function(model, properties) {
  if (this.isModel(model)) {
    return this.setModel(model, properties);
  } else if (this.isCollection(model)) {
    return this.setCollection(model, properties);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.setModel = function(model, properties) {
  var promises = [];

  properties = properties || {};

  if (model.isNew() && properties && properties.id) {
    promises.push(function() {
      return this.fetch(model, { id: properties.id }, this.findRelated(properties)).then(function(result) {
        return result;
      });
    }.bind(this));
  } else {
    promises.push(function() {
      return (model.isNew() || model.hasChanged()) ? model.save() : model;
    });
  }

  Object.keys(properties).forEach(function(key) {
    var value     = properties[key];
    var relation  = model[key] instanceof Function ? model[key].call(model) : null;
    var type      = relation ? relation.relatedData.type : 'scalar';
    var method    = 'set' + type.charAt(0).toUpperCase() + type.slice(1);
    var setter    = this[method].bind(this);

    promises.push(function(result) {
      return setter(result, key, value, relation).then(function() {
        return result;
      });
    });
  }.bind(this));

  return Promise.reduce(promises, function(result, promise) {
    return promise(result);
  }, []);
};

Manager.prototype.setBelongsTo = function(model, key, value, relation) {
  var Target    = relation.relatedData.target;
  var existing  = model.related(key);
  var target    = existing.isNew() ? Target.forge() : existing.clone();

  return this.save(target, value).then(function(target) {
    var fk = relation.relatedData.foreignKey;

    if (model.get(fk) !== target.id) {
      model.set(fk, target.id);
    }

    model.relations[key] = target;

    return (model.isNew() || model.hasChanged()) ? model.save() : model;
  });
};

Manager.prototype.setBelongsToMany = function(model, key, models, relation) {
  var existing = model.related(key);

  return Promise.cast(existing.length ? existing : existing.fetch()).then(function() {
    return this.setCollection(existing, models);
  }.bind(this)).then(function(targets) {

    return targets.mapThen(function(target) {
      if (!existing.findWhere({ id: target.id })) {
        return existing.attach(target);
      }
    }).then(function() {
      return existing.mapThen(function(target) {
        if (!targets.findWhere({ id: target.id })) {
          return existing.detach(target);
        }
      });
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setHasMany = function(model, key, models, relation) {
  var existing = model.related(key);

  return this.setCollection(existing, models).then(function(targets) {
    var fk = relation.relatedData.foreignKey;

    if (!fk) {
      throw new Error('`' + model.tableName + '#' + key + '` relation is missing `foreignKey` in `this.hasMany(Target, foreignKey)`');
    }

    return targets.mapThen(function(target) {
      var properties = {};

      properties[fk] = model.id;

      return this.save(target, properties).then(function(target) {
        existing.add(target);
      });
    }.bind(this)).then(function() {
      return existing.mapThen(function(target) {
        if (!targets.findWhere({ id: target.id })) {
          return target.destroy();
        }
      });
    });
  }.bind(this)).then(function() {
    return model;
  });
};

Manager.prototype.setScalar = Promise.method(function(model, key, value) {
  if (key.indexOf('_pivot_') === 0) {
    return model;
  }

  if (model.get(key) === value) {
    return model;
  }

  model.set(key, value);

  return model;
});

Manager.prototype.setCollection = function(existing, models) {
  models = models || [];

  return Promise.map(models, function(properties) {
    var model = existing.findWhere({ id: properties.id }) || existing.model.forge();

    return this.save(model, properties);
  }.bind(this)).then(function(results) {
    return this.bookshelf.Collection.forge(results);
  }.bind(this));
};

module.exports = Manager;
<commit_msg>Enforce belongsToMany IDs<commit_after>var Bookshelf = require('bookshelf');
var hooker    = require('hooker');
var path      = require('path');
var Promise   = require('bluebird');

var Manager = function(root, bookshelf) {
  if (!root) {
    throw new Error('Manager requires a path to model directory');
  }

  this.root = path.normalize(root);

  if (bookshelf) {
    this.initialize(bookshelf);
  } else {
    hooker.hook(Bookshelf, 'initialize', {
      once: true,
      post: this.initialize.bind(this)
    });
  }
};

Manager.manage = function(model) {
  if (!Manager.manages(model)) {
    Manager._managed.push(model);
  }

  return model;
};

Manager.manages = function(model) {
  if (!model instanceof Function) {
    return false;
  }

  return Manager._managed.indexOf(model) !== -1
};

Manager._managed = [];

Manager.prototype.initialize = function(bookshelf) {
  this.bookshelf  = bookshelf;
  this.knex       = this.bookshelf.knex;
  this.schema     = this.knex.schema;

  bookshelf.plugin('registry');

  hooker.hook(bookshelf, ['collection', 'model'], function(name, value) {
    if (!value) {
      return hooker.preempt(this.get(name));
    }
  }.bind(this));

  return this;
};

Manager.prototype._cache = {};

Manager.prototype.create = function(name, properties) {
  var Model = this.get(name);
  var model = new Model();

  return this.save(model, properties).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.debug = function(debug) {
  var level = 1;
  var methods = [
    'create',
    'fetch',
    'forge',
    'get',
    'load',
    'save',
    'saveCollection',
    'saveModel',
    'set',
    'setBelongsTo',
    'setBelongsToMany',
    'setCollection',
    'setHasMany',
    'setModel',
    'setScalar',
  ];

  var pre = function(name) {
    var indent  = new Array(level++).join('  ');
    var sliced  = Array.prototype.slice.call(arguments, 1);
    var args    = sliced.map(function(arg) {
      if (this.isCollection(arg)) {
        return '[Collection] (' + arg.length + ')';
      }

      if (this.isModel(arg)) {
        return '[Model `' + arg.tableName + '@' + arg.id + '`]';
      }

      return (JSON.stringify(arg) || 'null').split('\n').join('\n' + indent + '   ');
    }.bind(this)).join(',\n' + indent + '   ');

    console.log(indent, '<' + name + '>', '\n' + indent + '  ', args);
  };

  var post = function(result, name) {
    if (result && result.then) {
      result.then(function() {
        console.log(new Array(--level).join('  '), '</' + name + '>');

        return arguments[0];
      });
    };
  };

  if (typeof debug === 'undefined') {
    debug = true;
  }

  if (debug) {
    hooker.hook(this, methods, {
      passName: true,
      pre:      pre,
      post:     post
    });
  } else {
    hooker.unhook(this, methods);
  }

  return this;
};

Manager.prototype.fetch = function(name, properties, related) {
  var model = this.forge(name, properties);

  return model.fetch({
    withRelated: related,
  });
};

Manager.prototype.findRelated = function(properties, paths) {
  var related = [];

  properties  = properties || {};
  paths       = paths || [];

  for (var key in properties) {
    var value = properties[key];
    var ctor  = value ? value.constructor : null;

    if (ctor === Array) {
      related.push(paths.concat([key]).join('.'));

      if (value.length) {
        related = related.concat(this.findRelated(value[0], paths.concat([key])));
      }
    }

    if (ctor === Object) {
      related.push(paths.concat([key]).join('.'));

      related = related.concat(this.findRelated(value, paths.concat([key])));
    }
  }

  return related;
};

Manager.prototype.forge = function(name, properties) {
  var Model = this.get(name);

  // Model may already be instantiated
  if (Model instanceof this.bookshelf.Model) {
    Model = Model.constructor;
  }

  return Model.forge(properties);
};

Manager.prototype.get = function(Model) {
  if (!this.bookshelf) {
    throw new Error('Manager has not been initialized with instance of Bookshelf');
  }

  var name;

  if (typeof Model === 'string') {
    name = Model;

    if (this._cache[name]) {
      return this._cache[name];
    }

    var file = path.join(this.root, name);

    try {
      Model = require(file);
    } catch (e) {
      throw new Error('Could not find module `' + name + '` at `' + file + '.js`');
    }
  }

  if (Manager.manages(Model)) {
    Model = Model(this.bookshelf);
  }

  if (!this.isModel(Model) && !this.isCollection(Model)) {
    throw new Error('Expected a String, Model, Collection, or a Managed Model/Collection, got: ' + typeof Model);
  }

  if (this.isCollection(Model) && typeof Model.prototype.model === 'string') {
    Model.prototype.model = this.get(Model.prototype.model);
  }

  if (name) {
    if (this.isModel(Model)) {
      this._cache[name] = this.bookshelf.model(name, Model);
    } else if (this.isCollection(Model)) {
      this._cache[name] = this.bookshelf.collection(name, Model);
    }
  }

  return Model;
};

Manager.prototype.isModel = function(model) {
  if (!model || this.isCollection(model)) {
    return false;
  }

  return model instanceof this.bookshelf.Model || model.prototype instanceof this.bookshelf.Model;
};

Manager.prototype.isCollection = function(model) {
  if (!model) {
    return false;
  }

  return model instanceof this.bookshelf.Collection || model.prototype instanceof this.bookshelf.Collection;
};

Manager.prototype.save = function(model, properties) {
  if (this.isModel(model)) {
    return this.saveModel(model, properties);
  } else if (this.isCollection(model)) {
    return this.saveCollection(model, properties);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.saveCollection = function(collection, models) {
  return collection.mapThen(function(model) {
    return (model.isNew() || model.hasChanged()) ? model.save() : model;
  }).then(function() {
    return this.setCollection(collection, models);
  }.bind(this)).then(function(targets) {
    return targets.mapThen(function(target) {
      collection.add(target);

      return (target.isNew() || target.hasChanged()) ? target.save() : target;
    });
  }).then(function() {
    return collection;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.saveModel = function(model, properties) {
  return this.setModel(model, properties).then(function(result) {
    return (result.isNew() || result.hasChanged()) ? result.save() : result;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
}

Manager.prototype.set = function(model, properties) {
  if (this.isModel(model)) {
    return this.setModel(model, properties);
  } else if (this.isCollection(model)) {
    return this.setCollection(model, properties);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.setModel = function(model, properties) {
  var promises = [];

  properties = properties || {};

  if (model.isNew() && properties && properties.id) {
    promises.push(function() {
      return this.fetch(model, { id: properties.id }, this.findRelated(properties)).then(function(result) {
        return result;
      });
    }.bind(this));
  } else {
    promises.push(function() {
      return (model.isNew() || model.hasChanged()) ? model.save() : model;
    });
  }

  Object.keys(properties).forEach(function(key) {
    var value     = properties[key];
    var relation  = model[key] instanceof Function ? model[key].call(model) : null;
    var type      = relation ? relation.relatedData.type : 'scalar';
    var method    = 'set' + type.charAt(0).toUpperCase() + type.slice(1);
    var setter    = this[method].bind(this);

    promises.push(function(result) {
      return setter(result, key, value, relation).then(function() {
        return result;
      });
    });
  }.bind(this));

  return Promise.reduce(promises, function(result, promise) {
    return promise(result);
  }, []);
};

Manager.prototype.setBelongsTo = function(model, key, value, relation) {
  var Target    = relation.relatedData.target;
  var existing  = model.related(key);
  var target    = existing.isNew() ? Target.forge() : existing.clone();

  return this.save(target, value).then(function(target) {
    var fk = relation.relatedData.foreignKey;

    if (model.get(fk) !== target.id) {
      model.set(fk, target.id);
    }

    model.relations[key] = target;

    return (model.isNew() || model.hasChanged()) ? model.save() : model;
  });
};

Manager.prototype.setBelongsToMany = function(model, key, models, relation) {
  var existing = model.related(key);

  return Promise.cast(existing.length ? existing : existing.fetch()).then(function() {
    return this.setCollection(existing, models);
  }.bind(this)).then(function(targets) {
    // Enforce attach/detach IDs
    existing.relatedData.parentId = model.id;
    existing.relatedData.parentFk = model.id;

    return targets.mapThen(function(target) {
      if (!existing.findWhere({ id: target.id })) {
        return existing.attach(target);
      }
    }).then(function() {
      return existing.mapThen(function(target) {
        if (!targets.findWhere({ id: target.id })) {
          return existing.detach(target);
        }
      });
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setHasMany = function(model, key, models, relation) {
  var existing = model.related(key);

  return this.setCollection(existing, models).then(function(targets) {
    var fk = relation.relatedData.foreignKey;

    if (!fk) {
      throw new Error('`' + model.tableName + '#' + key + '` relation is missing `foreignKey` in `this.hasMany(Target, foreignKey)`');
    }

    return targets.mapThen(function(target) {
      var properties = {};

      properties[fk] = model.id;

      return this.save(target, properties).then(function(target) {
        existing.add(target);
      });
    }.bind(this)).then(function() {
      return existing.mapThen(function(target) {
        if (!targets.findWhere({ id: target.id })) {
          return target.destroy();
        }
      });
    });
  }.bind(this)).then(function() {
    return model;
  });
};

Manager.prototype.setScalar = Promise.method(function(model, key, value) {
  if (key.indexOf('_pivot_') === 0) {
    return model;
  }

  if (model.get(key) === value) {
    return model;
  }

  model.set(key, value);

  return model;
});

Manager.prototype.setCollection = function(existing, models) {
  models = models || [];

  return Promise.map(models, function(properties) {
    var model = existing.findWhere({ id: properties.id }) || existing.model.forge();

    return this.save(model, properties);
  }.bind(this)).then(function(results) {
    return this.bookshelf.Collection.forge(results);
  }.bind(this));
};

module.exports = Manager;
<|endoftext|>


<commit_before>var State = require('./state')
  , SessionStore = require('./stores/session')
  , MissingStateError = require('./errors/missingstateerror')
  , dispatch = require('./utils').dispatch
  , dispatchReal = dispatch
  , flatten = require('utils-flatten')
  , uri = require('url')
  , debug = require('debug')('flowstate');

function Manager(options, store) {
  if (!store) { store = new SessionStore(options); }

  this._store = store;
}

Manager.prototype._complete = function(options, err, req, res, next) {
  var self = this
    , store = this._store

  var cont = options.continue;
  //var through = options.through;
  var getHandle = options.getHandle || function(req) {
    return (req.query && req.query.state) || (req.body && req.body.state);
  }

  debug('complete %O (handle: %s, modified: %o, new: %o)', req.state, req.state.handle,
    req.state.isModified(), req.state.isNew());

  function dispatch(ystate) {
    return self._dispatch(options, err, req, res, next, ystate);
  }

  function proceed(h, ystate) {
    if (!h) {
      console.log('P0');

      // TODO: Clean this up
      /*
      if (through) {
        return self._through(through, err, req, res, next);
      }
      */

      console.log('P00');
      console.log(err);

      // No state to resume.  `next` middleware is expected to implement
      // default behavior for responding to the request.
      if (options.postFns) {
        dispatchReal(options.postFns)(err, req, res, function(err) {
          if (cont) {
            console.log('NEED TO CONTINUE TO: ' + cont);
            res.redirect(cont);
            return;
          }

          return next(err);
        });
        return;
      } else {
        if (cont) {
          console.log('NEED TO DEF CONTINUE TO: ' + cont);
          res.redirect(cont);
          return;
        }

        return next(err);
      }
    }

    store.load(req, h, function(ierr, state) {
      if (ierr) { return err ? next(err) : next(ierr); }
      if (!state) {
        if (err) { return next(err); }
        return (ystate && ystate.state)
          ? next(new MissingStateError("Failed to load parent state", h))
          : next(new MissingStateError("Failed to load state", h));
      }

      // Resume the parent state by setting its state at `req.state` and
      // dispatching.  The state that is yeilding control back to the parent
      // state is made available at `req.yieldState` so the context can be used
      // to inform how to continuing processing the request.
      req.state = new State(req, state, h);
      dispatch(ystate);
    });
  }

  if (req._state) {
    console.log('C1');

    // The state to be resumed has been loaded in an optimized manner.  Dispatch
    // directly to the state, yielding the current state, avoiding any
    // unnecessary operations against the state store.  Specifically, the state
    // being resumed is already loaded and the yeilding state is not persisted
    // and therefore does not need to be destroyed.  Furthermore, the yielding
    // state has parent state, and does not need saved in order to be kept.
    req.state = req._state;
    delete req._state;
    return dispatch();
  } else {
    console.log('C2');

    function continue1() {
      if (req.state.isExternal()) {
        console.log('C2-1');
        console.log(req.state);

        if (req.state.isModified()) {
          // NEW
          console.log('IN COMPLETE');

          return self._continue(null, req, res, next);
        }

        proceed(null, req.state);
      } else if (req.state.isNew()) {
        console.log('C2-2');

        // The current state is a new state, and the first state to be completed
        // in this transaction.  Resume the parent state, as indicated by the
        // state parameter carried in the request.
        proceed(getHandle(req), req.state);
      } else {
        console.log('C2-3');

        // The current state is an existing state.  Resume the parent state as
        // indicated by the parent property of the state itself.
        return proceed(req.state.state, req.state);
        // NEW:
        //return proceed(req.state.returnTo, req.state);
      }
    }

    function continue0() {
    // The current state is complete, and is yielding to its parent state, if
    // any.
    //if (req.state.isKeeped()) {
    //if (0) {
    if (req.state.returnTo) {
      // NEW condition, can be cleaned up, probably
      if (req.state.isNew() || req.state.isModified()) {
        req.state.save(function(ierr) {
          if (ierr) { return next(ierr); }
          continue1();
        });
      } else if (req.state.state || !req.state.isModified()) {
        // TODO: Clean this up and make it more generic
        //if (req.state.returnTo && !req.state.state && req.url !== req.state.returnTo) {
        //if (req.state.returnTo && req.url !== req.state.returnTo) {
        //if (ru !== req.state.recipient) {
        //  return continue1();
        //}
        if (!req.state.isComplete()) {
          return continue1();
        }

        // Resuming a parent state, current state is implicity complete
        req.state.destroy(function(ierr) {
          if (ierr) { return err ? next(err) : next(ierr); }
          continue1();
        });
      } else {
        continue1();
      }
    } else {
      // Remove the current state from any persistent storage, due to the
      // fact that it is complete.
      req.state.destroy(function(ierr) {
        if (ierr) { return err ? next(err) : next(ierr); }
        continue1();
      });
    }
  }
  } // continue0

  //if (options.postFns && req.state._meta.preventDefault == true) {
  //if (options.postFns) {
  if (0) {
    dispatchReal(options.postFns)(err, req, res, function(err) {
      // TODO: handle err, with test case
      continue0();
    });
  } else {
    continue0();
  }
}

/*
Manager.prototype._through = function(through, err, req, res, next) {
  req.yieldState = req.state;
  req.state = new State(req, { name: through }, undefined, false, true);
  return this._dispatch(null, err, req, res, next);
}
*/

// TODO: clean up these arguments, in particular ystate being last
Manager.prototype._dispatch = function(options, err, req, res, next, ystate) {
  // NEW yieldstate return to option.
  //var through = options ? options.through : null;

  // dead code, can be deleted
  /*
  if (through && through !== req.state.name) {
    req._state = req.state;
    req.state = new State(req, { name: through }, undefined, false, true);
    req.state.state = req._state.handle;
    return this._dispatch(null, err, req, res, next);
  }
  */

  debug('resume %O (handle: %s) yielding %O', req.state, req.state.handle, req.yieldState);

  var self = this;

  function cont(err) {
    // TODO: Test case for transition error
    self._continue(err, req, res, next, ystate);
  }

  // TODO: Make sure transition errors get plumbed through correctly
  //this._yield(options, err, req, res, cont);
  cont();
}

Manager.prototype._continue = function(err, req, res, next, ystate) {
  //name = uri.parse(name).pathname; // TODO: test case for query parsing

  // NEW
  var url = ystate && ystate.returnTo;
  if (url) {
    return res.redirect(url);
  }

  return;

  /*
  if (!state) { return next(new Error("Unknown state '" + name + "'")); }
  if (!state.resume) { return next(new Error("Unable to resume state '" + name + "'")); }

  // TODO: Allow for options here?
  var complete = completeState(this, {});
  var completeError = completeStateError(this, {});
  var unfinished = unfinishedState();

  var stack = state.resume.concat([complete, completeError]);
  if (state.exit) {
    stack.push.apply(stack, state.exit)
  }
  stack.push(unfinished);

  req._skipCompleteStateError = false;
  dispatch(stack)(err, req, res, next);
  */
}

Manager.prototype._yield = function(options, err, req, res, next) {
  return next();

  // FIXME: there are two tests (in sso/oauth and sso/oauth2 that dependend on this code)
  //        factor the fix somewhere else.  It is probalby the `postFns` related code here

  // TODO: Comment out this whole piece and fix tests.  Nothing depends on yields anymore
  /*
  var t = req.state.name || (req.yieldState && req.yieldState.returnTo)
    , f = req.yieldState.name || req.originalUrl || req.url;

  t = uri.parse(t).pathname; // TODO: test case for query parsing
  f = uri.parse(f).pathname; // TODO: test case for query parsing

  req.yieldStateStack = req.yieldStateStack || [];
  req.yieldStateStack.unshift(req.yieldState);

  var stack = this._yielders[t + '|' + f];
  if (!stack) {
    if (options && options.postFns) {
      dispatchReal(options.postFns)(err, req, res, function(err) {
        // TODO: handle err, with test case
        return next(err);
      });
      return;
    }

    return next(err);
  }
  dispatch(stack)(err, req, res, next);
  */
}

module.exports = Manager;
<commit_msg>Remove Manager#_complete function.<commit_after>var State = require('./state')
  , SessionStore = require('./stores/session')
  , MissingStateError = require('./errors/missingstateerror')
  , dispatch = require('./utils').dispatch
  , dispatchReal = dispatch
  , flatten = require('utils-flatten')
  , uri = require('url')
  , debug = require('debug')('flowstate');

function Manager(options, store) {
  if (!store) { store = new SessionStore(options); }

  this._store = store;
}

/*
Manager.prototype._through = function(through, err, req, res, next) {
  req.yieldState = req.state;
  req.state = new State(req, { name: through }, undefined, false, true);
  return this._dispatch(null, err, req, res, next);
}
*/

// TODO: clean up these arguments, in particular ystate being last
Manager.prototype._dispatch = function(options, err, req, res, next, ystate) {
  // NEW yieldstate return to option.
  //var through = options ? options.through : null;

  // dead code, can be deleted
  /*
  if (through && through !== req.state.name) {
    req._state = req.state;
    req.state = new State(req, { name: through }, undefined, false, true);
    req.state.state = req._state.handle;
    return this._dispatch(null, err, req, res, next);
  }
  */

  debug('resume %O (handle: %s) yielding %O', req.state, req.state.handle, req.yieldState);

  var self = this;

  function cont(err) {
    // TODO: Test case for transition error
    self._continue(err, req, res, next, ystate);
  }

  // TODO: Make sure transition errors get plumbed through correctly
  //this._yield(options, err, req, res, cont);
  cont();
}

Manager.prototype._continue = function(err, req, res, next, ystate) {
  //name = uri.parse(name).pathname; // TODO: test case for query parsing

  // NEW
  var url = ystate && ystate.returnTo;
  if (url) {
    return res.redirect(url);
  }

  return;

  /*
  if (!state) { return next(new Error("Unknown state '" + name + "'")); }
  if (!state.resume) { return next(new Error("Unable to resume state '" + name + "'")); }

  // TODO: Allow for options here?
  var complete = completeState(this, {});
  var completeError = completeStateError(this, {});
  var unfinished = unfinishedState();

  var stack = state.resume.concat([complete, completeError]);
  if (state.exit) {
    stack.push.apply(stack, state.exit)
  }
  stack.push(unfinished);

  req._skipCompleteStateError = false;
  dispatch(stack)(err, req, res, next);
  */
}

Manager.prototype._yield = function(options, err, req, res, next) {
  return next();

  // FIXME: there are two tests (in sso/oauth and sso/oauth2 that dependend on this code)
  //        factor the fix somewhere else.  It is probalby the `postFns` related code here

  // TODO: Comment out this whole piece and fix tests.  Nothing depends on yields anymore
  /*
  var t = req.state.name || (req.yieldState && req.yieldState.returnTo)
    , f = req.yieldState.name || req.originalUrl || req.url;

  t = uri.parse(t).pathname; // TODO: test case for query parsing
  f = uri.parse(f).pathname; // TODO: test case for query parsing

  req.yieldStateStack = req.yieldStateStack || [];
  req.yieldStateStack.unshift(req.yieldState);

  var stack = this._yielders[t + '|' + f];
  if (!stack) {
    if (options && options.postFns) {
      dispatchReal(options.postFns)(err, req, res, function(err) {
        // TODO: handle err, with test case
        return next(err);
      });
      return;
    }

    return next(err);
  }
  dispatch(stack)(err, req, res, next);
  */
}

module.exports = Manager;
<|endoftext|>


<commit_before>var async = require('async');
var Blockchain = require('./blockchain.js');
var Compiler = require('./compiler.js');
var fs = require('fs');
var utils = require('ethereumjs-util');
var optionalCallback = require('./utils.js').optionalCallback;
var pkg = require('../package.json');
require('datejs');

Manager = function () {
  this.blockchain = new Blockchain();
}

Manager.prototype.createAccounts = function(initialAccounts, callback) {
  var self = this;
  // Add accounts for testing purposes.
  if (typeof(initialAccounts) == 'function') {
    return initialAccounts();
  }

  async.times(initialAccounts, function(n, next) {
    self.blockchain.addAccount(next);
  }, callback);
};

Manager.prototype.mine = function() {
  this.blockchain.mine();
}

Manager.prototype.reset = function() {
  this.blockchain = new Blockchain();
}

Manager.prototype.jump = function(text) {
  var seconds = (Date.parse(text) - Date.parse("now")) / 1000 | 0;
  this.blockchain.increaseTime(seconds);
}

Manager.prototype.response = function(params, result) {
  return {"id":params.id,"jsonrpc":"2.0","result":result};
}

// Handle individual requests.

Manager.prototype.request = function(params, cb) {
  if (Object.prototype.toString.call(params) === '[object Array]') {
    var results = [];
    for (var i=0; i < params.length; i+=1) {
      results.push(this.request(params[i]));
    }
    return cb(null, results);
  }

  var fn = this[params.method];
  var args = params.params || [];

  if (cb) {
    var that = this;
    args.push(function (err, res) {
      cb(err, that.response(params, res));
    });
  }

  var result = fn.apply(this, args);

  return this.response(params, result);
};

Manager.prototype.eth_accounts = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.accountAddresses());
};

Manager.prototype.eth_blockNumber = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.toHex(this.blockchain.blockNumber()));
};

Manager.prototype.eth_coinbase = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.coinbase);
};

Manager.prototype.eth_mining = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, false);
};

Manager.prototype.eth_hashrate = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, '0x' + utils.intToHex(0));
};

Manager.prototype.eth_gasPrice = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, '0x' + this.blockchain.gasPrice());
};

Manager.prototype.eth_getBalance = function(address, block_number, callback) {
  if (callback !== undefined) this.blockchain.getBalance(address, callback);
  return "please use an async call";
};

Manager.prototype.ethersim_setBalance = function(address, balance, callback) {
  this.blockchain.setBalance(address, balance, callback);
};

Manager.prototype.eth_getCode = function(address, block_number, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getCode(address));
};

Manager.prototype.eth_getBlockByNumber = function(block_number, include_transactions, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getBlockByNumber(block_number));
};

Manager.prototype.eth_getBlockByHash = function(block_hash, include_transactions, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getBlockByHash(block_hash));
};

Manager.prototype.eth_getTransactionReceipt = function(tx_hash, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getTransactionReceipt(tx_hash));
};

Manager.prototype.eth_getTransactionByHash = function(tx_hash, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getTransactionByHash(tx_hash));
}

Manager.prototype.eth_getTransactionCount = function(address, block_number, callback) {
  callback = optionalCallback(callback);
  this.blockchain.getTransactionCount(address, callback);
}

Manager.prototype.eth_sendTransaction = function(tx_data, callback) {
  callback = optionalCallback(callback);
  this.blockchain.queueTransaction(tx_data, callback);
};

Manager.prototype.eth_sendRawTransaction = function(rawTx, callback) {
  callback = optionalCallback(callback);
  return callback(new Error("eth_sendRawTransaction not implemented yet, but it will be soon"));
};

Manager.prototype.eth_call = function(tx_data, block_number, callback) {
  callback = optionalCallback(callback);
  this.blockchain.queueCall(tx_data, callback);
};

Manager.prototype.eth_newBlockFilter = function(callback) {
  var filter_id = utils.addHexPrefix(utils.intToHex(this.blockchain.latest_filter_id));
  this.blockchain.latest_filter_id += 1;
  callback(null, filter_id);
};

Manager.prototype.eth_getFilterChanges = function(filter_id, callback) {
  var blockHash = this.blockchain.latestBlock().hash().toString("hex");
  // Mine a block after each request to getFilterChanges so block filters work.
  this.blockchain.mine();
  callback = optionalCallback(callback);
  return callback(null, [blockHash]);
};

Manager.prototype.eth_uninstallFilter = function(filter_id, callback) {
  callback(null, true);
};

Manager.prototype.eth_getCompilers = function(callback) {
  callback(null, ["solidity"]);
}

Manager.prototype.eth_compileSolidity = function(code, callback) {
  var compiler = new Compiler();
  fs.writeFileSync("/tmp/solCompiler.sol", code);
  compiled = compiler.compile_solidity("/tmp/solCompiler.sol");
  callback = optionalCallback(callback);
  return callback(null, compiled);
};

Manager.prototype.web3_clientVersion = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, "EtherSim/v" + pkg.version + "/ethereum-js")
};

/* Functions for testing purposes only. */

Manager.prototype.evm_snapshot = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.snapshot());
};

Manager.prototype.evm_revert = function(snapshot_id, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.revert(snapshot_id));
};

module.exports = Manager;
<commit_msg>catch specific exception that is causing issues with embark tests<commit_after>var async = require('async');
var Blockchain = require('./blockchain.js');
var Compiler = require('./compiler.js');
var fs = require('fs');
var utils = require('ethereumjs-util');
var optionalCallback = require('./utils.js').optionalCallback;
var pkg = require('../package.json');
require('datejs');

Manager = function () {
  this.blockchain = new Blockchain();
}

Manager.prototype.createAccounts = function(initialAccounts, callback) {
  var self = this;
  // Add accounts for testing purposes.
  if (typeof(initialAccounts) == 'function') {
    return initialAccounts();
  }

  async.times(initialAccounts, function(n, next) {
    self.blockchain.addAccount(next);
  }, callback);
};

Manager.prototype.mine = function() {
  this.blockchain.mine();
}

Manager.prototype.reset = function() {
  this.blockchain = new Blockchain();
}

Manager.prototype.jump = function(text) {
  var seconds = (Date.parse(text) - Date.parse("now")) / 1000 | 0;
  this.blockchain.increaseTime(seconds);
}

Manager.prototype.response = function(params, result) {
  return {"id":params.id,"jsonrpc":"2.0","result":result};
}

// Handle individual requests.

Manager.prototype.request = function(params, cb) {
  if (Object.prototype.toString.call(params) === '[object Array]') {
    var results = [];
    for (var i=0; i < params.length; i+=1) {
      results.push(this.request(params[i]));
    }
    return cb(null, results);
  }

  var fn = this[params.method];
  var args = params.params || [];

  if (cb) {
    var that = this;
    args.push(function (err, res) {
      try {
        return cb(err, that.response(params, res));
      } catch (err) {
        if (err == ["TypeError: Cannot read property 'stopWatching' of undefined]"]) {
          // TODO: weird edge case when deploying embark tests
          return cb(err, null);
        }
        else {
          return cb(err, that.response(params, res));
        }
      }
    });
  }

  var result = fn.apply(this, args);

  return this.response(params, result);
};

Manager.prototype.eth_accounts = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.accountAddresses());
};

Manager.prototype.eth_blockNumber = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.toHex(this.blockchain.blockNumber()));
};

Manager.prototype.eth_coinbase = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.coinbase);
};

Manager.prototype.eth_mining = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, false);
};

Manager.prototype.eth_hashrate = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, '0x' + utils.intToHex(0));
};

Manager.prototype.eth_gasPrice = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, '0x' + this.blockchain.gasPrice());
};

Manager.prototype.eth_getBalance = function(address, block_number, callback) {
  if (callback !== undefined) this.blockchain.getBalance(address, callback);
  return "please use an async call";
};

Manager.prototype.ethersim_setBalance = function(address, balance, callback) {
  this.blockchain.setBalance(address, balance, callback);
};

Manager.prototype.eth_getCode = function(address, block_number, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getCode(address));
};

Manager.prototype.eth_getBlockByNumber = function(block_number, include_transactions, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getBlockByNumber(block_number));
};

Manager.prototype.eth_getBlockByHash = function(block_hash, include_transactions, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getBlockByHash(block_hash));
};

Manager.prototype.eth_getTransactionReceipt = function(tx_hash, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getTransactionReceipt(tx_hash));
};

Manager.prototype.eth_getTransactionByHash = function(tx_hash, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getTransactionByHash(tx_hash));
}

Manager.prototype.eth_getTransactionCount = function(address, block_number, callback) {
  callback = optionalCallback(callback);
  this.blockchain.getTransactionCount(address, callback);
}

Manager.prototype.eth_sendTransaction = function(tx_data, callback) {
  callback = optionalCallback(callback);
  this.blockchain.queueTransaction(tx_data, callback);
};

Manager.prototype.eth_sendRawTransaction = function(rawTx, callback) {
  callback = optionalCallback(callback);
  return callback(new Error("eth_sendRawTransaction not implemented yet, but it will be soon"));
};

Manager.prototype.eth_call = function(tx_data, block_number, callback) {
  callback = optionalCallback(callback);
  this.blockchain.queueCall(tx_data, callback);
};

Manager.prototype.eth_newBlockFilter = function(callback) {
  var filter_id = utils.addHexPrefix(utils.intToHex(this.blockchain.latest_filter_id));
  this.blockchain.latest_filter_id += 1;
  callback(null, filter_id);
};

Manager.prototype.eth_getFilterChanges = function(filter_id, callback) {
  var blockHash = this.blockchain.latestBlock().hash().toString("hex");
  // Mine a block after each request to getFilterChanges so block filters work.
  this.blockchain.mine();
  callback = optionalCallback(callback);
  return callback(null, [blockHash]);
};

Manager.prototype.eth_uninstallFilter = function(filter_id, callback) {
  callback(null, true);
};

Manager.prototype.eth_getCompilers = function(callback) {
  callback(null, ["solidity"]);
}

Manager.prototype.eth_compileSolidity = function(code, callback) {
  var compiler = new Compiler();
  fs.writeFileSync("/tmp/solCompiler.sol", code);
  compiled = compiler.compile_solidity("/tmp/solCompiler.sol");
  callback = optionalCallback(callback);
  return callback(null, compiled);
};

Manager.prototype.web3_clientVersion = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, "EtherSim/v" + pkg.version + "/ethereum-js")
};

/* Functions for testing purposes only. */

Manager.prototype.evm_snapshot = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.snapshot());
};

Manager.prototype.evm_revert = function(snapshot_id, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.revert(snapshot_id));
};

module.exports = Manager;
<|endoftext|>


<commit_before>var irc = require('IRC-js/lib/irc'),
    io = require('Socket.IO-node'),
    sys  = require('sys');

var webClients = [];
var servers = [];

function MartIrc(options) {
    if (! (this instanceof arguments.callee)) {
        return new arguments.callee(arguments);
    }

    var self = this;

    self.settings = {
        port: options.port,
        encoding: options.encoding
    };

    self.init();
};

MartIrc.prototype.init = function() {
    var self = this;

    self.httpServer = self.createHTTPServer();
    self.httpServer.listen(self.settings.port);
    sys.log('Server started on PORT ' + self.settings.port);

}

MartIrc.prototype.createHTTPServer = function() {
    var self = this;

    var app = require('express/lib/express').createServer();
    var socket = io.listen(app);

    socket.on('connection', function(client){

        client.on('message', function(clientMessage){
            console.log("got a message :: "+ clientMessage.type);

            switch(clientMessage.type)
        {
            case 'connect':

                var server = new irc({
                    server: clientMessage.data.ircHost,
                    port: clientMessage.data.ircPort,
                    nick: clientMessage.data.nick,
                    encoding: self.settings.encoding
                });

                channels = clientMessage.data.channels;

                server.connect(function() {
                    setTimeout(function() {
                        for(i in channels) {
                            server.join(channels[i]);
                        }
                    }, 2000);
                });

                server.addListener('privmsg', function(msg) {
                    nick = msg.person.nick;
                    chan = msg.params[0];
                    message = msg.params[1];

                    var data = {channel: chan, from:nick, msg:message};

                    console.log("IRC new: "+msg.params[0]+" - "+msg.person.nick+":"+msg.params[1]+"\n");

                    if(webClients.length != 0) {
                        for(i in webClients) {
                            webClient = webClients[i];

                            if(webClient.server == this) {

                                for(j in webClient.channels) {

                                    if(chan.toLowerCase() == webClient.channels[j].toLowerCase()) {

                                        webClient.client.send(data);

                                    }
                                }
                            }
                        }
                    }

                });

                webClients.push({session:client.sessionId,client:client, server:server, channels: channels});
                console.log("got a client :: "+client.sessionId+" :: "+webClients.length);

                client.send({msgs:[],channels: channels});

                break;

            case 'privmsg':
                console.log("got a message for " + clientMessage.data.channel + " :: "+ clientMessage.data.message);

                if(webClients.length != 0) {
                    for(i in webClients) {
                        webClient = webClients[i];

                        if(webClient.session == client.sessionId) {
                            //TODO: change the from nickname
                            webClient.client.send({channel: clientMessage.data.channel, from:'me', msg:clientMessage.data.message});
                            webClient.server.privmsg(clientMessage.data.channel, clientMessage.data.message);
                        }
                    }
                }

                break;

        }
        });

        client.on('disconnect', function(){
            for(i in webClients) {
                if(webClients[i].session == client.sessionId) {
                    webClients[i].server.quit("Leaving");
                    webClients.splice(i,1);
                }
            }
            console.log("disconnect");
        });
    });

    return app;

};

module.exports = MartIrc;
<commit_msg>Added webClients as an "instance" variable<commit_after>var irc = require('IRC-js/lib/irc'),
    io = require('Socket.IO-node'),
    sys  = require('sys');

function MartIrc(options) {
    if (! (this instanceof arguments.callee)) {
        return new arguments.callee(arguments);
    }

    var self = this;

    self.settings = {
        port: options.port,
        encoding: options.encoding
    };

    self.init();
};

MartIrc.prototype.init = function() {
    var self = this;

    self.webClients = [];

    self.httpServer = self.createHTTPServer();
    self.httpServer.listen(self.settings.port);
    sys.log('Server started on PORT ' + self.settings.port);

}

MartIrc.prototype.createHTTPServer = function() {
    var self = this;

    var app = require('express/lib/express').createServer();
    var socket = io.listen(app);

    socket.on('connection', function(client){

        client.on('message', function(clientMessage){
            console.log("got a message :: "+ clientMessage.type);

            switch(clientMessage.type)
        {
            case 'connect':

                var server = new irc({
                    server: clientMessage.data.ircHost,
                    port: clientMessage.data.ircPort,
                    nick: clientMessage.data.nick,
                    encoding: self.settings.encoding
                });

                channels = clientMessage.data.channels;

                server.connect(function() {
                    setTimeout(function() {
                        for(i in channels) {
                            server.join(channels[i]);
                        }
                    }, 2000);
                });

                server.addListener('privmsg', function(msg) {
                    nick = msg.person.nick;
                    chan = msg.params[0];
                    message = msg.params[1];

                    var data = {channel: chan, from:nick, msg:message};

                    console.log("IRC new: "+msg.params[0]+" - "+msg.person.nick+":"+msg.params[1]+"\n");

                    if(self.webClients.length != 0) {
                        for(i in self.webClients) {
                            self.webClient = self.webClients[i];

                            if(self.webClient.server == this) {

                                for(j in self.webClient.channels) {

                                    if(chan.toLowerCase() == self.webClient.channels[j].toLowerCase()) {

                                        self.webClient.client.send(data);

                                    }
                                }
                            }
                        }
                    }

                });

                self.webClients.push({session:client.sessionId,client:client, server:server, channels: channels});
                console.log("got a client :: "+client.sessionId+" :: "+self.webClients.length);

                client.send({msgs:[],channels: channels});

                break;

            case 'privmsg':
                console.log("got a message for " + clientMessage.data.channel + " :: "+ clientMessage.data.message);

                if(self.webClients.length != 0) {
                    for(i in self.webClients) {
                        self.webClient = self.webClients[i];

                        if(self.webClient.session == client.sessionId) {
                            //TODO: change the from nickname
                            self.webClient.client.send({channel: clientMessage.data.channel, from:'me', msg:clientMessage.data.message});
                            self.webClient.server.privmsg(clientMessage.data.channel, clientMessage.data.message);
                        }
                    }
                }

                break;

        }
        });

        client.on('disconnect', function(){
            for(i in self.webClients) {
                if(self.webClients[i].session == client.sessionId) {
                    self.webClients[i].server.quit("Leaving");
                    self.webClients.splice(i,1);
                }
            }
            console.log("disconnect");
        });
    });

    return app;

};

module.exports = MartIrc;
<|endoftext|>