<commit_before>/*
 * Copyright 2013 Eduardo Lundgren, All Rights Reserved.
 *
 * Code licensed under the BSD License:
 * https://github.com/eduardolundgren/blob/master/LICENSE.md
 *
 * @author Eduardo Lundgren <eduardolundgren@gmail.com>
 */

// -- Requires -----------------------------------------------------------------
var async = require('async'),
    base = require('../base'),
    clc = require('cli-color'),
    fs = require('fs'),
    git = require('../git'),
    open = require('open'),
    path = require('path'),
    logger = require('../logger'),
    stripNewLines,
    issueImpl = require('./is').Impl;

// -- Constructor --------------------------------------------------------------
function PullRequest(options) {
    this.options = options;

    if (!options.repo) {
        logger.error('You must specify a Git repository to run this command');
    }

    this.issue = new issueImpl(options);
}

// -- Constants ----------------------------------------------------------------
PullRequest.DETAILS = {
    options: {
        'all'     : Boolean,
        'branch'  : String,
        'close'   : Boolean,
        'comment' : String,
        'detailed': Boolean,
        'fetch'   : Boolean,
        'fwd'     : String,
        'list'    : Boolean,
        'merge'   : Boolean,
        'number'  : Number,
        'open'    : Boolean,
        'rebase'  : Boolean,
        'repo'    : String,
        'state'   : [ 'open', 'closed' ],
        'submit'  : String,
        'title'   : String,
        'user'    : String
    },
    shorthands: {
        'a': [ '--all' ],
        'b': [ '--branch' ],
        'C': [ '--close' ],
        'c': [ '--comment' ],
        'd': [ '--detailed' ],
        'f': [ '--fetch' ],
        'l': [ '--list' ],
        'M': [ '--merge' ],
        'n': [ '--number' ],
        'o': [ '--open' ],
        'R': [ '--rebase' ],
        'r': [ '--repo' ],
        'S': [ '--state' ],
        's': [ '--submit' ],
        't': [ '--title' ],
        'u': [ '--user' ]
    },
    description: 'Provides a set of util commands to work with Pull Requests.'
};

PullRequest.FETCH_TYPE_CHECKOUT = 'checkout';

PullRequest.FETCH_TYPE_MERGE = 'merge';

PullRequest.FETCH_TYPE_REBASE = 'rebase';

PullRequest.FETCH_TYPE_SILENT = 'silent';

PullRequest.STATE_CLOSED = 'closed';

PullRequest.STATE_OPEN = 'open';

// -- Commands -----------------------------------------------------------------
PullRequest.prototype.options = null;

PullRequest.prototype.issues = null;

PullRequest.prototype.run = function() {
    var instance = this,
        options = instance.options,
        config = base.getGlobalConfig(),
        fetchType;

    options.state = options.state || PullRequest.STATE_OPEN;
    options.number = options.number || instance.getPullRequestNumberFromBranch_();
    options.pullBranch = instance.getBranchNameFromPullNumber_(options.number);

    if (!options.list) {
        options.branch = options.branch || config.default_branch;
    }

    if (options.close) {
        logger.logTemplate('{{prefix}} [info] Closing pull request {{greenBright "#" options.number}}', {
            options: options
        });

        instance.close(function(err) {
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{link}}', { options: options }));
        });
    }

    if (options.comment) {
        logger.logTemplate('{{prefix}} [info] Adding comment on pull request {{greenBright "#" options.number}}', {
            options: options
        });

        instance.issue.comment(function(err) {
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{link}}', { options: options }));
        });
    }

    if (options.fetch) {
        fetchType = PullRequest.FETCH_TYPE_CHECKOUT;

        if (options.merge) {
            fetchType = PullRequest.FETCH_TYPE_MERGE;
        }
        else if (options.rebase) {
            fetchType = PullRequest.FETCH_TYPE_REBASE;
        }

        logger.logTemplateFile('pr-fetch.handlebars', {
            currentBranch: options.currentBranch,
            options: options
        });

        instance.fetch(fetchType, logger.defaultCallback);
    }
    else if (options.merge || options.rebase) {
        logger.logTemplateFile('pr-merge.handlebars', {
            options: options
        });

        instance.merge();
    }

    if (options.fwd) {
        logger.logTemplate('{{prefix}} [info] Forwarding pull request {{greenBright "#" options.number}} to {{{magentaBright "@" options.fwd}}}', {
            options: options
        });

        instance.forward(function(err, pull) {
            if (pull) {
                options.forwardedPull = pull.number;
            }
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{forwardedLink}}', { options: options }));
        });
    }

    if (options.list) {
        if (options.all) {
            logger.logTemplate('{{prefix}} [info] Listing {{options.state}} pull requests for {{greenBright options.user}}', {
                options: options
            });

            instance.listFromAllRepositories(function(err) {
                logger.defaultCallback(err, null, false);
            });
        }
        else {
            logger.logTemplate('{{prefix}} [info] Listing {{options.state}} pull requests on {{greenBright options.user "/" options.repo}}', {
                options: options
            });

            instance.list(options.repo, function(err) {
                logger.defaultCallback(err, null, false);
            });
        }
    }

    if (options.open) {
        logger.logTemplate('{{prefix}} [info] Opening pull request {{greenBright "#" options.number}}', {
            options: options
        });

        instance.open(function(err) {
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{link}}', { options: options }));
        });
    }

    if (options.submit) {
        logger.logTemplate('{{prefix}} [info] Submitting pull request to {{{magentaBright "@" options.submit}}}', {
            options: options
        });

        instance.submit(options.submit, function(err, pull) {
            if (pull) {
                options.submittedPull = pull.number;

                if (config.open_pull_request_in_browser) {
                    open(pull.html_url);
                }
            }
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{submittedLink}}', { options: options }));
        });
    }
};

PullRequest.prototype.close = function(opt_callback) {
    var instance = this,
        options = instance.options,
        operations,
        pull;

    operations = [
        function(callback) {
            instance.getPullRequest_(function(err, data) {
                if (!err) {
                    pull = data;
                }
                callback(err);
            });
        },
        function(callback) {
            instance.updatePullRequest_(
                pull.title, pull.body, PullRequest.STATE_CLOSED, callback);
        },
        function(callback) {
            if (options.pullBranch === options.currentBranch) {
                git.checkout(options.branch, null, callback);
            }
            else {
                callback();
            }
        },
        function(callback) {
            if (options.pullBranch) {
                git.exec('branch', [ '-D', options.pullBranch ]);
            }

            callback();
        }
    ];

    async.series(operations, function(err) {
        opt_callback && opt_callback(err);
    });
};

PullRequest.prototype.checkPullRequestIntegrity_ = function(originalError, user, opt_callback) {
    var instance = this,
        options = instance.options,
        payload,
        pull;

    payload = {
        user: user,
        repo: options.repo,
        state: PullRequest.STATE_OPEN
    };

    base.github.pullRequests.getAll(payload, function(err, pulls) {
        if (!err) {
            pulls.forEach(function(data) {
                if ((data.base.ref === options.branch) &&
                    (data.head.ref === options.currentBranch) &&
                    (data.base.user.login === user) &&
                    (data.head.user.login === options.user)) {

                    pull = data;
                    originalError = null;
                    return;
                }
            });
        }

        opt_callback && opt_callback(originalError, pull);
    });
};

PullRequest.prototype.fetch = function(opt_type, opt_callback) {
    var instance = this,
        options = instance.options,
        headBranch,
        operations,
        pull,
        repoUrl;

    operations = [
        function(callback) {
            instance.getPullRequest_(function(err, data) {
                if (!err) {
                    pull = data;
                    headBranch = pull.head.ref;
                    repoUrl = pull.head.repo.git_url;
                }
                callback(err);
            });
        },
        function(callback) {
            git.exec('fetch', [ repoUrl, headBranch + ':' + options.pullBranch ], callback);
        },
        function(callback) {
            if (opt_type === PullRequest.FETCH_TYPE_REBASE) {
                git.merge(options.pullBranch, true, true, callback);
            }
            else if (opt_type === PullRequest.FETCH_TYPE_MERGE) {
                git.merge(options.pullBranch, false, true, callback);
            }
            else if (opt_type === PullRequest.FETCH_TYPE_CHECKOUT) {
                git.checkout(options.pullBranch, null, callback);
            }
            else {
                callback();
            }
        }
    ];

    async.series(operations, function(err) {
        opt_callback && opt_callback(err, pull);
    });
};

PullRequest.prototype.forward = function(opt_callback) {
    var instance = this,
        options = instance.options,
        config = base.getGlobalConfig(),
        operations,
        pull;

    operations = [
        function(callback) {
            instance.fetch(PullRequest.FETCH_TYPE_SILENT, callback);
        },
        function(callback) {
            instance.submit(options.fwd, function(err, data) {
                pull = data;
                callback(err);
            });
        },
        function(callback) {
            instance.close(callback);
        }
    ];

    async.series(operations, function(err) {
        opt_callback && opt_callback(err, pull);
    });
};

PullRequest.prototype.getPullRequest_ = function(opt_callback) {
    var instance = this,
        options = instance.options,
        payload;

    payload = {
        number: options.number,
        repo: options.repo,
        user: options.user
    };

    base.github.pullRequests.get(payload, opt_callback);
};

PullRequest.prototype.getBranchNameFromPullNumber_ = function(number) {
    if (number) {
        return logger.compileTemplate(
            base.getGlobalConfig().branch_name, { number: number });
    }
};

PullRequest.prototype.getPullRequestNumberFromBranch_ = function() {
    var instance = this,
        options = instance.options,
        match;

    if (options.currentBranch) {
        match = options.currentBranch.match(/\d+$/);

        return match && match[0];
    }
};

PullRequest.prototype.getPullsTemplateJson_ = function(pulls, opt_callback) {
    var instance = this,
        options = instance.options,
        branch,
        branches,
        json;

    branches = {};
    json = {
        branches: []
    };

    pulls.forEach(function(pull) {
        branch = pull.base.ref;

        if (!options.branch || options.branch === branch) {
            branches[branch] = branches[branch] || [];
            branches[branch].push(pull);
        }
    });

    Object.keys(branches).forEach(function(branch) {
        json.branches.push({
            name: branch,
            pulls: branches[branch],
            total: branches[branch].length
        });
    });

    opt_callback && opt_callback(null, json);
};

PullRequest.prototype.list = function(repo, opt_callback) {
    var instance = this,
        options = instance.options,
        json,
        operations,
        payload,
        pulls;

    payload = {
        repo: repo,
        state: options.state,
        user: options.user
    };

    operations = [
        function(callback) {
            base.github.pullRequests.getAll(payload, function(err, data) {
                if (!err) {
                    pulls = data;
                }
                callback(err);
            });
        },
        function(callback) {
            instance.getPullsTemplateJson_(pulls, function(err, data) {
                if (!err) {
                    json = data;
                }
                callback(err);
            });
        }
    ];

    async.series(operations, function(err) {
        if (!err && pulls.length) {
            json.repo = repo;
            json.user = options.user;
            json.detailed = options.detailed;
            logger.logTemplateFile('pr.handlebars', json);
        }

        opt_callback && opt_callback(err);
    });
};

PullRequest.prototype.listFromAllRepositories = function() {
    var instance = this;

    base.github.repos.getAll({ type: 'all' }, function(err, repositories) {
        repositories.forEach(function(repository) {
            instance.list(repository.name);
        });
    });
};

PullRequest.prototype.merge = function(opt_callback) {
    var instance = this,
        options = instance.options,
        operations;

    operations = [
        function(callback) {
            git.checkout(options.branch, null, callback);
        },
        function(callback) {
            git.merge(options.pullBranch, options.rebase, false, function(err, data) {
                console.log(data);
                callback(err);
            });
        },
        function(callback) {
            instance.close(callback);
        }
    ];

    async.series(operations, opt_callback);
};

PullRequest.prototype.open = function(opt_callback) {
    var instance = this;

    instance.getPullRequest_(function(err, pull) {
        instance.updatePullRequest_(
            pull.title, pull.body, PullRequest.STATE_OPEN, opt_callback);
    });
};

PullRequest.prototype.submit = function(user, opt_callback) {
    var instance = this,
        options = instance.options,
        operations,
        pullBranch;

    pullBranch = options.pullBranch || options.currentBranch;

    operations = [
        function(callback) {
            git.exec('push', [ 'origin', pullBranch ], callback);
        },
        function(callback) {
            base.github.pullRequests.create({
                base: options.branch,
                body: '',
                head: options.user + ':' + pullBranch,
                repo: options.repo,
                title: options.title || pullBranch,
                user: user
            }, callback);
        }
    ];

    async.series(operations, function(err, results) {
        if (err) {
            instance.checkPullRequestIntegrity_(err, user, opt_callback);
        }
        else {
            opt_callback && opt_callback(err, results[1]);
        }
    });
};

PullRequest.prototype.updatePullRequest_ = function(title, opt_body, state, opt_callback) {
    var instance = this,
        options = instance.options,
        payload;

    if (opt_body) {
        opt_body = logger.applyReplacements(opt_body);
    }

    payload = {
        body: opt_body,
        number: options.number,
        repo: options.repo,
        state: state,
        title: title,
        user: options.user
    };

    base.github.pullRequests.update(payload, function(err, pull) {
        opt_callback && opt_callback(err, pull);
    });
};

exports.Impl = PullRequest;<commit_msg>Source formatting<commit_after>/*
 * Copyright 2013 Eduardo Lundgren, All Rights Reserved.
 *
 * Code licensed under the BSD License:
 * https://github.com/eduardolundgren/blob/master/LICENSE.md
 *
 * @author Eduardo Lundgren <eduardolundgren@gmail.com>
 */

// -- Requires -----------------------------------------------------------------
var async = require('async'),
    base = require('../base'),
    clc = require('cli-color'),
    fs = require('fs'),
    git = require('../git'),
    open = require('open'),
    path = require('path'),
    logger = require('../logger'),
    stripNewLines,
    issueImpl = require('./is').Impl;

// -- Constructor --------------------------------------------------------------
function PullRequest(options) {
    this.options = options;

    if (!options.repo) {
        logger.error('You must specify a Git repository to run this command');
    }

    this.issue = new issueImpl(options);
}

// -- Constants ----------------------------------------------------------------
PullRequest.DETAILS = {
    options: {
        'all'     : Boolean,
        'branch'  : String,
        'close'   : Boolean,
        'comment' : String,
        'detailed': Boolean,
        'fetch'   : Boolean,
        'fwd'     : String,
        'list'    : Boolean,
        'merge'   : Boolean,
        'number'  : Number,
        'open'    : Boolean,
        'rebase'  : Boolean,
        'repo'    : String,
        'state'   : [ 'open', 'closed' ],
        'submit'  : String,
        'title'   : String,
        'user'    : String
    },
    shorthands: {
        'a': [ '--all' ],
        'b': [ '--branch' ],
        'C': [ '--close' ],
        'c': [ '--comment' ],
        'd': [ '--detailed' ],
        'f': [ '--fetch' ],
        'l': [ '--list' ],
        'M': [ '--merge' ],
        'n': [ '--number' ],
        'o': [ '--open' ],
        'R': [ '--rebase' ],
        'r': [ '--repo' ],
        'S': [ '--state' ],
        's': [ '--submit' ],
        't': [ '--title' ],
        'u': [ '--user' ]
    },
    description: 'Provides a set of util commands to work with Pull Requests.'
};

PullRequest.FETCH_TYPE_CHECKOUT = 'checkout';

PullRequest.FETCH_TYPE_MERGE = 'merge';

PullRequest.FETCH_TYPE_REBASE = 'rebase';

PullRequest.FETCH_TYPE_SILENT = 'silent';

PullRequest.STATE_CLOSED = 'closed';

PullRequest.STATE_OPEN = 'open';

// -- Commands -----------------------------------------------------------------
PullRequest.prototype.options = null;

PullRequest.prototype.issues = null;

PullRequest.prototype.run = function() {
    var instance = this,
        options = instance.options,
        config = base.getGlobalConfig(),
        fetchType;

    options.state = options.state || PullRequest.STATE_OPEN;
    options.number = options.number || instance.getPullRequestNumberFromBranch_();
    options.pullBranch = instance.getBranchNameFromPullNumber_(options.number);

    if (!options.list) {
        options.branch = options.branch || config.default_branch;
    }

    if (options.close) {
        logger.logTemplate('{{prefix}} [info] Closing pull request {{greenBright "#" options.number}}', {
            options: options
        });

        instance.close(function(err) {
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{link}}', { options: options }));
        });
    }

    if (options.comment) {
        logger.logTemplate('{{prefix}} [info] Adding comment on pull request {{greenBright "#" options.number}}', {
            options: options
        });

        instance.issue.comment(function(err) {
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{link}}', { options: options }));
        });
    }

    if (options.fetch) {
        fetchType = PullRequest.FETCH_TYPE_CHECKOUT;

        if (options.merge) {
            fetchType = PullRequest.FETCH_TYPE_MERGE;
        }
        else if (options.rebase) {
            fetchType = PullRequest.FETCH_TYPE_REBASE;
        }

        logger.logTemplateFile('pr-fetch.handlebars', {
            currentBranch: options.currentBranch,
            options: options
        });

        instance.fetch(fetchType, logger.defaultCallback);
    }
    else if (options.merge || options.rebase) {
        logger.logTemplateFile('pr-merge.handlebars', {
            options: options
        });

        instance.merge();
    }

    if (options.fwd) {
        logger.logTemplate('{{prefix}} [info] Forwarding pull request {{greenBright "#" options.number}} to {{{magentaBright "@" options.fwd}}}', {
            options: options
        });

        instance.forward(function(err, pull) {
            if (pull) {
                options.forwardedPull = pull.number;
            }
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{forwardedLink}}', { options: options }));
        });
    }

    if (options.list) {
        if (options.all) {
            logger.logTemplate('{{prefix}} [info] Listing {{options.state}} pull requests for {{greenBright options.user}}', {
                options: options
            });

            instance.listFromAllRepositories(function(err) {
                logger.defaultCallback(err, null, false);
            });
        }
        else {
            logger.logTemplate('{{prefix}} [info] Listing {{options.state}} pull requests on {{greenBright options.user "/" options.repo}}', {
                options: options
            });

            instance.list(options.repo, function(err) {
                logger.defaultCallback(err, null, false);
            });
        }
    }

    if (options.open) {
        logger.logTemplate('{{prefix}} [info] Opening pull request {{greenBright "#" options.number}}', {
            options: options
        });

        instance.open(function(err) {
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{link}}', { options: options }));
        });
    }

    if (options.submit) {
        logger.logTemplate('{{prefix}} [info] Submitting pull request to {{{magentaBright "@" options.submit}}}', {
            options: options
        });

        instance.submit(options.submit, function(err, pull) {
            if (pull) {
                options.submittedPull = pull.number;

                if (config.open_pull_request_in_browser) {
                    open(pull.html_url);
                }
            }
            logger.defaultCallback(
                err, null, logger.compileTemplate('{{submittedLink}}', { options: options }));
        });
    }
};

PullRequest.prototype.close = function(opt_callback) {
    var instance = this,
        options = instance.options,
        operations,
        pull;

    operations = [
        function(callback) {
            instance.getPullRequest_(function(err, data) {
                if (!err) {
                    pull = data;
                }
                callback(err);
            });
        },
        function(callback) {
            instance.updatePullRequest_(
                pull.title, pull.body, PullRequest.STATE_CLOSED, callback);
        },
        function(callback) {
            if (options.pullBranch === options.currentBranch) {
                git.checkout(options.branch, null, callback);
            }
            else {
                callback();
            }
        },
        function(callback) {
            if (options.pullBranch) {
                git.exec('branch', [ '-D', options.pullBranch ]);
            }

            callback();
        }
    ];

    async.series(operations, opt_callback);
};

PullRequest.prototype.checkPullRequestIntegrity_ = function(originalError, user, opt_callback) {
    var instance = this,
        options = instance.options,
        payload,
        pull;

    payload = {
        user: user,
        repo: options.repo,
        state: PullRequest.STATE_OPEN
    };

    base.github.pullRequests.getAll(payload, function(err, pulls) {
        if (!err) {
            pulls.forEach(function(data) {
                if ((data.base.ref === options.branch) &&
                    (data.head.ref === options.currentBranch) &&
                    (data.base.user.login === user) &&
                    (data.head.user.login === options.user)) {

                    pull = data;
                    originalError = null;
                    return;
                }
            });
        }

        opt_callback && opt_callback(originalError, pull);
    });
};

PullRequest.prototype.fetch = function(opt_type, opt_callback) {
    var instance = this,
        options = instance.options,
        headBranch,
        operations,
        pull,
        repoUrl;

    operations = [
        function(callback) {
            instance.getPullRequest_(function(err, data) {
                if (!err) {
                    pull = data;
                    headBranch = pull.head.ref;
                    repoUrl = pull.head.repo.git_url;
                }
                callback(err);
            });
        },
        function(callback) {
            git.exec('fetch', [ repoUrl, headBranch + ':' + options.pullBranch ], callback);
        },
        function(callback) {
            if (opt_type === PullRequest.FETCH_TYPE_REBASE) {
                git.merge(options.pullBranch, true, true, callback);
            }
            else if (opt_type === PullRequest.FETCH_TYPE_MERGE) {
                git.merge(options.pullBranch, false, true, callback);
            }
            else if (opt_type === PullRequest.FETCH_TYPE_CHECKOUT) {
                git.checkout(options.pullBranch, null, callback);
            }
            else {
                callback();
            }
        }
    ];

    async.series(operations, function(err) {
        opt_callback && opt_callback(err, pull);
    });
};

PullRequest.prototype.forward = function(opt_callback) {
    var instance = this,
        options = instance.options,
        config = base.getGlobalConfig(),
        operations,
        pull;

    operations = [
        function(callback) {
            instance.fetch(PullRequest.FETCH_TYPE_SILENT, callback);
        },
        function(callback) {
            instance.submit(options.fwd, function(err, data) {
                pull = data;
                callback(err);
            });
        },
        function(callback) {
            instance.close(callback);
        }
    ];

    async.series(operations, function(err) {
        opt_callback && opt_callback(err, pull);
    });
};

PullRequest.prototype.getPullRequest_ = function(opt_callback) {
    var instance = this,
        options = instance.options,
        payload;

    payload = {
        number: options.number,
        repo: options.repo,
        user: options.user
    };

    base.github.pullRequests.get(payload, opt_callback);
};

PullRequest.prototype.getBranchNameFromPullNumber_ = function(number) {
    if (number) {
        return logger.compileTemplate(
            base.getGlobalConfig().branch_name, { number: number });
    }
};

PullRequest.prototype.getPullRequestNumberFromBranch_ = function() {
    var instance = this,
        options = instance.options,
        match;

    if (options.currentBranch) {
        match = options.currentBranch.match(/\d+$/);

        return match && match[0];
    }
};

PullRequest.prototype.getPullsTemplateJson_ = function(pulls, opt_callback) {
    var instance = this,
        options = instance.options,
        branch,
        branches,
        json;

    branches = {};
    json = {
        branches: []
    };

    pulls.forEach(function(pull) {
        branch = pull.base.ref;

        if (!options.branch || options.branch === branch) {
            branches[branch] = branches[branch] || [];
            branches[branch].push(pull);
        }
    });

    Object.keys(branches).forEach(function(branch) {
        json.branches.push({
            name: branch,
            pulls: branches[branch],
            total: branches[branch].length
        });
    });

    opt_callback && opt_callback(null, json);
};

PullRequest.prototype.list = function(repo, opt_callback) {
    var instance = this,
        options = instance.options,
        json,
        operations,
        payload,
        pulls;

    payload = {
        repo: repo,
        state: options.state,
        user: options.user
    };

    operations = [
        function(callback) {
            base.github.pullRequests.getAll(payload, function(err, data) {
                if (!err) {
                    pulls = data;
                }
                callback(err);
            });
        },
        function(callback) {
            instance.getPullsTemplateJson_(pulls, function(err, data) {
                if (!err) {
                    json = data;
                }
                callback(err);
            });
        }
    ];

    async.series(operations, function(err) {
        if (!err && pulls.length) {
            json.repo = repo;
            json.user = options.user;
            json.detailed = options.detailed;
            logger.logTemplateFile('pr.handlebars', json);
        }

        opt_callback && opt_callback(err);
    });
};

PullRequest.prototype.listFromAllRepositories = function() {
    var instance = this;

    base.github.repos.getAll({ type: 'all' }, function(err, repositories) {
        repositories.forEach(function(repository) {
            instance.list(repository.name);
        });
    });
};

PullRequest.prototype.merge = function(opt_callback) {
    var instance = this,
        options = instance.options,
        operations;

    operations = [
        function(callback) {
            git.checkout(options.branch, null, callback);
        },
        function(callback) {
            git.merge(options.pullBranch, options.rebase, false, function(err, data) {
                console.log(data);
                callback(err);
            });
        },
        function(callback) {
            instance.close(callback);
        }
    ];

    async.series(operations, opt_callback);
};

PullRequest.prototype.open = function(opt_callback) {
    var instance = this;

    instance.getPullRequest_(function(err, pull) {
        instance.updatePullRequest_(
            pull.title, pull.body, PullRequest.STATE_OPEN, opt_callback);
    });
};

PullRequest.prototype.submit = function(user, opt_callback) {
    var instance = this,
        options = instance.options,
        operations,
        pullBranch;

    pullBranch = options.pullBranch || options.currentBranch;

    operations = [
        function(callback) {
            git.exec('push', [ 'origin', pullBranch ], callback);
        },
        function(callback) {
            base.github.pullRequests.create({
                base: options.branch,
                body: '',
                head: options.user + ':' + pullBranch,
                repo: options.repo,
                title: options.title || pullBranch,
                user: user
            }, callback);
        }
    ];

    async.series(operations, function(err, results) {
        if (err) {
            instance.checkPullRequestIntegrity_(err, user, opt_callback);
        }
        else {
            opt_callback && opt_callback(err, results[1]);
        }
    });
};

PullRequest.prototype.updatePullRequest_ = function(title, opt_body, state, opt_callback) {
    var instance = this,
        options = instance.options,
        payload;

    if (opt_body) {
        opt_body = logger.applyReplacements(opt_body);
    }

    payload = {
        body: opt_body,
        number: options.number,
        repo: options.repo,
        state: state,
        title: title,
        user: options.user
    };

    base.github.pullRequests.update(payload, opt_callback);
};

exports.Impl = PullRequest;<|endoftext|>


<commit_before>/*
 * barcode generator - code128
 */

var gm = require('gm');

const BARMAP = [
  [2,1,2,2,2,2], [2,2,2,1,2,2], [2,2,2,2,2,1], [1,2,1,2,2,3], [1,2,1,3,2,2],
  [1,3,1,2,2,2], [1,2,2,2,1,3], [1,2,2,3,1,2], [1,3,2,2,1,2], [2,2,1,2,1,3],
  [2,2,1,3,1,2], [2,3,1,2,1,2], [1,1,2,2,3,2], [1,2,2,1,3,2], [1,2,2,2,3,1],
  [1,1,3,2,2,2], [1,2,3,1,2,2], [1,2,3,2,2,1], [2,2,3,2,1,1], [2,2,1,1,3,2],
  [2,2,1,2,3,1], [2,1,3,2,1,2], [2,2,3,1,1,2], [3,1,2,1,3,1], [3,1,1,2,2,2],
  [3,2,1,1,2,2], [3,2,1,2,2,1], [3,1,2,2,1,2], [3,2,2,1,1,2], [3,2,2,2,1,1],
  [2,1,2,1,2,3], [2,1,2,3,2,1], [2,3,2,1,2,1], [1,1,1,3,2,3], [1,3,1,1,2,3],
  [1,3,1,3,2,1], [1,1,2,3,1,3], [1,3,2,1,1,3], [1,3,2,3,1,1], [2,1,1,3,1,3],
  [2,3,1,1,1,3], [2,3,1,3,1,1], [1,1,2,1,3,3], [1,1,2,3,3,1], [1,3,2,1,3,1],
  [1,1,3,1,2,3], [1,1,3,3,2,1], [1,3,3,1,2,1], [3,1,3,1,2,1], [2,1,1,3,3,1],
  [2,3,1,1,3,1], [2,1,3,1,1,3], [2,1,3,3,1,1], [2,1,3,1,3,1], [3,1,1,1,2,3],
  [3,1,1,3,2,1], [3,3,1,1,2,1], [3,1,2,1,1,3], [3,1,2,3,1,1], [3,3,2,1,1,1],
  [3,1,4,1,1,1], [2,2,1,4,1,1], [4,3,1,1,1,1], [1,1,1,2,2,4], [1,1,1,4,2,2],
  [1,2,1,1,2,4], [1,2,1,4,2,1], [1,4,1,1,2,2], [1,4,1,2,2,1], [1,1,2,2,1,4],
  [1,1,2,4,1,2], [1,2,2,1,1,4], [1,2,2,4,1,1], [1,4,2,1,1,2], [1,4,2,2,1,1],
  [2,4,1,2,1,1], [2,2,1,1,1,4], [4,1,3,1,1,1], [2,4,1,1,1,2], [1,3,4,1,1,1],
  [1,1,1,2,4,2], [1,2,1,1,4,2], [1,2,1,2,4,1], [1,1,4,2,1,2], [1,2,4,1,1,2],
  [1,2,4,2,1,1], [4,1,1,2,1,2], [4,2,1,1,1,2], [4,2,1,2,1,1], [2,1,2,1,4,1],
  [2,1,4,1,2,1], [4,1,2,1,2,1], [1,1,1,1,4,3], [1,1,1,3,4,1], [1,3,1,1,4,1],
  [1,1,4,1,1,3], [1,1,4,3,1,1], [4,1,1,1,1,3], [4,1,1,3,1,1], [1,1,3,1,4,1],
  [1,1,4,1,3,1], [3,1,1,1,4,1], [4,1,1,1,3,1], [2,1,1,4,1,2], [2,1,1,2,1,4],
  [2,1,1,2,3,2], [2,3,3,1,1,1,2], [2,1,1,1,3,3]
];

const CODEMAPS = {
  'A': [
    ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
    '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
    '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
    'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',
    '\\', ']', '^', '_', 'NUL', 'SOH', 'STX', 'ETX', 'EOT', 'ENQ', 'ACK', 'BEL',
    'BS', 'HT', 'LF', 'VT', 'FF', 'CR', 'SO', 'SI', 'DLE', 'DC1', 'DC2', 'DC3',
    'DC4', 'NAK', 'SYN', 'ETB', 'CAN', 'EM', 'SUB', 'ESC', 'FS', 'GS', 'RS', 'US',
    'FNC3', 'FNC3', 'SHIFTB', 'CODEC', 'CODEB', 'FNC4', 'FNC1'
  ],
  'B': [
    ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
    '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
    '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
    'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',
    '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
    'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
    'z', '{', '|', '}', '~', 'DEL', 'FNC3', 'FNC2', 'SHIFTA', 'CODEC', 'FNC4',
    'CODEA', 'FNC1'
  ],
  'C': [
    '00', '01', '02', '03', '04', '05', '06', '07', '08', '09',
    '10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
    '20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
    '30', '31', '32', '33', '34', '35', '36', '37', '38', '39',
    '40', '41', '42', '43', '44', '45', '46', '47', '48', '49',
    '50', '51', '52', '53', '54', '55', '56', '57', '58', '59',
    '60', '61', '62', '63', '64', '65', '66', '67', '68', '69',
    '70', '71', '72', '73', '74', '75', '76', '77', '78', '79',
    '80', '81', '82', '83', '84', '85', '86', '87', '88', '89',
    '90', '91', '92', '93', '94', '95', '96', '97', '98', '99',
    'CODEB', 'CODEA', 'FNC1',
  ]
};

const STARTA = BARMAP[103];
const STARTB = BARMAP[104];
const STARTC = BARMAP[105];
const STOP   = BARMAP[106];

const START = {
  'A': STARTA,
  'B': STARTB,
  'C': STARTC
};

function getVal(mode, ch) {
  return i = mode.toUpperCase() in CODEMAPS &&
    CODEMAPS[mode.toUpperCase()].indexOf(ch) ||
    0;
}

module.exports.createCode = function (options, callback) {
  if (!options.data) {
    return callback(new Error('No data given'), {});
  }

  if (!options.w || !options.h) {
    return callback(new Error('Width and Height must be non-zero'), {});
  }

console.log('Checking mode')

  var mode = options.mode || 'B';

console.log('Mode set at ' + mode);

  // START + CHECK + END + DATA
  var baseWidth = 11 + 11 + 13 + options.data.length * 11;
  var barWidth = options.w / baseWidth >> 0;

  if (!barWidth) {
    return callback(new Error('Width will result in a degenerate barcode'), {});
  }

  // encode
  // refactor...
  var encoded = [ START[mode] ];
  var checkSum = (mode == 'A') ? 103 : (mode == 'B' ? 104 : 105);
  for(var i in options.data) {
    i = parseInt(i); // shoudn't i already be a number? It's not.
    var val = getVal(mode, options.data[i] );
    encoded.push( BARMAP[val] );
    checkSum += (i + 1) * val;
  }

  // add on check digit
  encoded.push(BARMAP[ checkSum % 103 ]);
  encoded.push(STOP);

  var img = gm(options.w, options.h, options.bgcolor),
    count = 0,
    pos = 0,
    w;

  img.stroke(options.barcolor, 1);
  pos = (options.w - baseWidth * barWidth) / 2 >> 0;

  for (var i in encoded) {

    for (var k in encoded[i]) {
      w = encoded[i][k] * barWidth;
      // only draw even indecies
      if ( ! (k % 2) ) {
        for (var m = 0; m < w; m++) {
          img.drawLine(pos + m, 0, pos + m, options.h);
        }
      }

      pos += w;
    }
  }

  img.stream(options.type, function (err, stdout, stderr) {
    callback(err, stdout);
  });
};
<commit_msg>Updated some tihngs, put a refactor todo<commit_after>/*
 * barcode generator - code128
 */

var gm = require('gm');

const BARMAP = [
  [2,1,2,2,2,2], [2,2,2,1,2,2], [2,2,2,2,2,1], [1,2,1,2,2,3], [1,2,1,3,2,2],
  [1,3,1,2,2,2], [1,2,2,2,1,3], [1,2,2,3,1,2], [1,3,2,2,1,2], [2,2,1,2,1,3],
  [2,2,1,3,1,2], [2,3,1,2,1,2], [1,1,2,2,3,2], [1,2,2,1,3,2], [1,2,2,2,3,1],
  [1,1,3,2,2,2], [1,2,3,1,2,2], [1,2,3,2,2,1], [2,2,3,2,1,1], [2,2,1,1,3,2],
  [2,2,1,2,3,1], [2,1,3,2,1,2], [2,2,3,1,1,2], [3,1,2,1,3,1], [3,1,1,2,2,2],
  [3,2,1,1,2,2], [3,2,1,2,2,1], [3,1,2,2,1,2], [3,2,2,1,1,2], [3,2,2,2,1,1],
  [2,1,2,1,2,3], [2,1,2,3,2,1], [2,3,2,1,2,1], [1,1,1,3,2,3], [1,3,1,1,2,3],
  [1,3,1,3,2,1], [1,1,2,3,1,3], [1,3,2,1,1,3], [1,3,2,3,1,1], [2,1,1,3,1,3],
  [2,3,1,1,1,3], [2,3,1,3,1,1], [1,1,2,1,3,3], [1,1,2,3,3,1], [1,3,2,1,3,1],
  [1,1,3,1,2,3], [1,1,3,3,2,1], [1,3,3,1,2,1], [3,1,3,1,2,1], [2,1,1,3,3,1],
  [2,3,1,1,3,1], [2,1,3,1,1,3], [2,1,3,3,1,1], [2,1,3,1,3,1], [3,1,1,1,2,3],
  [3,1,1,3,2,1], [3,3,1,1,2,1], [3,1,2,1,1,3], [3,1,2,3,1,1], [3,3,2,1,1,1],
  [3,1,4,1,1,1], [2,2,1,4,1,1], [4,3,1,1,1,1], [1,1,1,2,2,4], [1,1,1,4,2,2],
  [1,2,1,1,2,4], [1,2,1,4,2,1], [1,4,1,1,2,2], [1,4,1,2,2,1], [1,1,2,2,1,4],
  [1,1,2,4,1,2], [1,2,2,1,1,4], [1,2,2,4,1,1], [1,4,2,1,1,2], [1,4,2,2,1,1],
  [2,4,1,2,1,1], [2,2,1,1,1,4], [4,1,3,1,1,1], [2,4,1,1,1,2], [1,3,4,1,1,1],
  [1,1,1,2,4,2], [1,2,1,1,4,2], [1,2,1,2,4,1], [1,1,4,2,1,2], [1,2,4,1,1,2],
  [1,2,4,2,1,1], [4,1,1,2,1,2], [4,2,1,1,1,2], [4,2,1,2,1,1], [2,1,2,1,4,1],
  [2,1,4,1,2,1], [4,1,2,1,2,1], [1,1,1,1,4,3], [1,1,1,3,4,1], [1,3,1,1,4,1],
  [1,1,4,1,1,3], [1,1,4,3,1,1], [4,1,1,1,1,3], [4,1,1,3,1,1], [1,1,3,1,4,1],
  [1,1,4,1,3,1], [3,1,1,1,4,1], [4,1,1,1,3,1], [2,1,1,4,1,2], [2,1,1,2,1,4],
  [2,1,1,2,3,2], [2,3,3,1,1,1,2], [2,1,1,1,3,3]
];

const CODEMAPS = {
  'A': [
    ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
    '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
    '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
    'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',
    '\\', ']', '^', '_', 'NUL', 'SOH', 'STX', 'ETX', 'EOT', 'ENQ', 'ACK', 'BEL',
    'BS', 'HT', 'LF', 'VT', 'FF', 'CR', 'SO', 'SI', 'DLE', 'DC1', 'DC2', 'DC3',
    'DC4', 'NAK', 'SYN', 'ETB', 'CAN', 'EM', 'SUB', 'ESC', 'FS', 'GS', 'RS', 'US',
    'FNC3', 'FNC3', 'SHIFTB', 'CODEC', 'CODEB', 'FNC4', 'FNC1'
  ],
  'B': [
    ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
    '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
    '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
    'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',
    '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
    'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
    'z', '{', '|', '}', '~', 'DEL', 'FNC3', 'FNC2', 'SHIFTA', 'CODEC', 'FNC4',
    'CODEA', 'FNC1'
  ],
  'C': [
    '00', '01', '02', '03', '04', '05', '06', '07', '08', '09',
    '10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
    '20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
    '30', '31', '32', '33', '34', '35', '36', '37', '38', '39',
    '40', '41', '42', '43', '44', '45', '46', '47', '48', '49',
    '50', '51', '52', '53', '54', '55', '56', '57', '58', '59',
    '60', '61', '62', '63', '64', '65', '66', '67', '68', '69',
    '70', '71', '72', '73', '74', '75', '76', '77', '78', '79',
    '80', '81', '82', '83', '84', '85', '86', '87', '88', '89',
    '90', '91', '92', '93', '94', '95', '96', '97', '98', '99',
    'CODEB', 'CODEA', 'FNC1',
  ]
};

const STARTA = BARMAP[103];
const STARTB = BARMAP[104];
const STARTC = BARMAP[105];
const STOP   = BARMAP[106];

const START = {
  'A': STARTA,
  'B': STARTB,
  'C': STARTC
};

function getVal(mode, ch) {
  return i = mode.toUpperCase() in CODEMAPS &&
    CODEMAPS[mode.toUpperCase()].indexOf(ch) ||
    0;
}

module.exports.createCode = function (options, callback) {
  if (!options.data) {
    return callback(new Error('No data given'), {});
  }

  if (!options.w || !options.h) {
    return callback(new Error('Width and Height must be non-zero'), {});
  }

  // @todo refactor ------------------------------------------------------------
  // we want to detect and optimize the best mode switching for the shortest
  // code and the best space utilization.

  var mode = options.mode || 'B';

  // START + CHECK + END + DATA
  var baseWidth = 11 + 11 + 13 + options.data.length * 11;
  var barWidth = options.w / baseWidth >> 0;

  if (!barWidth) {
    return callback(new Error('Width will result in a degenerate barcode'), {});
  }

  // encode
  var encoded = [ START[mode] ];
  var checkSum = (mode == 'A') ? 103 : (mode == 'B' ? 104 : 105);
  for(var i in options.data) {
    i = parseInt(i); // shoudn't i already be a number? It's not.
    var val = getVal(mode, options.data[i] );
    encoded.push( BARMAP[val] );
    checkSum += (i + 1) * val;
  }

  // add on check digit
  encoded.push(BARMAP[ checkSum % 103 ]);
  encoded.push(STOP);

  // @todo end -----------------------------------------------------------------

  var img = gm(options.w, options.h, options.bgcolor),
    count = 0,
    pos = 0,
    w;

  img.stroke(options.barcolor, 1);
  pos = (options.w - baseWidth * barWidth) / 2 >> 0;

  for (var i in encoded) {

    for (var k in encoded[i]) {
      w = encoded[i][k] * barWidth;
      // only draw even indecies
      if ( ! (k % 2) ) {
        for (var m = 0; m < w; m++) {
          img.drawLine(pos + m, 0, pos + m, options.h);
        }
      }

      pos += w;
    }
  }

  img.stream(options.type, function (err, stdout, stderr) {
    callback(err, stdout);
  });
};
<|endoftext|>


<commit_before>var jsonServer = require('json-server')
var server = jsonServer.create();
var bodyParser = require('body-parser');
var router = "";
var middlewares = jsonServer.defaults()
var fs = require('fs');
var url  = require('url');
var _ = require('lodash');

var glob = require("glob")
var restData = {};

server.use(jsonServer.bodyParser);
glob("./data/*.mock.json", function (er, files) {
  // files is an array of filenames.
console.log("Found "+ files.length + " endpoint files");
  files.forEach(function (file) {
    var dataFile = require(file);

    restData[dataFile.endpoint] = dataFile.data;
    var urlPath = '';
    if (dataFile.endpoint == 'api') {
      urlPath = '/api';
    }
    else {
      urlPath = '/api/' + dataFile.endpoint+'*';
    }
    if (dataFile.querystrings) {
      server.all(urlPath, function (req, res) {
        var url_parts = url.parse(req.url, false);
        var query = req.url;
        var match = _.find(dataFile.querystrings, function (item) {
          return query.includes(item.endpoint);
        });

        if (match != undefined) {
          var jsonResponse = generateResponse(req, match);
          res.json(jsonResponse);
        }
        else {
          res.json(dataFile.data);
        }
      });
    }
    else{
       server.all(urlPath, function (req, res) {
        var jsonResponse = generateResponse(req, dataFile);
        res.json(jsonResponse);
      });
    }
  });

    var json = JSON.stringify(restData);
    fs.writeFile('./db.json', json);
    router = jsonServer.router(restData);

  startServer();
});

function generateResponse(request, data){
  var reqMethod = request.method.toLowerCase();
      var requestMethodExists = (data.hasOwnProperty(reqMethod) ? true: false);
      if (reqMethod === 'get') {
        if (requestMethodExists) {
          return data.get;
        }
        else {
          return data.data;
        }
      }
      else {
        if (requestMethodExists) {
         return data[reqMethod].data;
        }
        else{
          return {"status":"Data was received and the http method was "+reqMethod,"data": request.body} ;
        }
      }
}

function startServer() {
  server.use(jsonServer.rewriter({
    '/api/:resource': '/:resource'
  }));
  server.use(middlewares);
  server.use(router);

  var port = 3004;
  if (process.env.MOCK_API_HOST) {
    var urlParts = url.parse(process.env.MOCK_API_HOST, false);
    port = urlParts.host;
  }

  server.listen(port, function () {
    console.log('Mock API Server is running on port ' + port);
  })
}
<commit_msg>Mock api logging functionality<commit_after>var jsonServer = require('json-server')
var server = jsonServer.create();
var bodyParser = require('body-parser');
var router = "";
var middlewares = jsonServer.defaults()
var fs = require('fs');
var url  = require('url');
var _ = require('lodash');

var glob = require("glob")
var restData = {};

server.use(jsonServer.bodyParser);
server.use(function (req, res, next) {
  if (process.env.LOG_LEVEL && process.env.LOG_LEVEL === 'debug') {
    console.log(req.body);
  }
  next()
});

glob("./data/*.mock.json", function (er, files) {
  // files is an array of filenames.
console.log("Found "+ files.length + " endpoint files");
  files.forEach(function (file) {
    var dataFile = require(file);

    restData[dataFile.endpoint] = dataFile.data;
    var urlPath = '';
    if (dataFile.endpoint == 'api') {
      urlPath = '/api';
    }
    else {
      urlPath = '/api/' + dataFile.endpoint+'*';
    }
    if (dataFile.querystrings) {
      server.all(urlPath, function (req, res) {
        var url_parts = url.parse(req.url, false);
        var query = req.url;
        var match = _.find(dataFile.querystrings, function (item) {
          return query.includes(item.endpoint);
        });

        if (match != undefined) {
          var jsonResponse = generateResponse(req, match);
          res.json(jsonResponse);
        }
        else {
          res.json(dataFile.data);
        }
      });
    }
    else{
       server.all(urlPath, function (req, res) {
        var jsonResponse = generateResponse(req, dataFile);
        res.json(jsonResponse);
      });
    }
  });

    var json = JSON.stringify(restData);
    fs.writeFile('./db.json', json);
    router = jsonServer.router(restData);

  startServer();
});

function generateResponse(request, data){
  var reqMethod = request.method.toLowerCase();
      var requestMethodExists = (data.hasOwnProperty(reqMethod) ? true: false);
      if (reqMethod === 'get') {
        if (requestMethodExists) {
          return data.get;
        }
        else {
          return data.data;
        }
      }
      else {
        if (requestMethodExists) {
         return data[reqMethod].data;
        }
        else{
          return {"status":"Data was received and the http method was "+reqMethod,"data": request.body} ;
        }
      }
}

function startServer() {
  server.use(jsonServer.rewriter({
    '/api/:resource': '/:resource'
  }));
  server.use(middlewares);
  server.use(router);

  var port = 3004;
  if (process.env.MOCK_API_HOST) {
    var urlParts = url.parse(process.env.MOCK_API_HOST, false);
    port = urlParts.host;
  }

  server.listen(port, function () {
    console.log('Mock API Server is running on port ' + port);
  })
}
<|endoftext|>


<commit_before>/*
 * Optics / command.js
 * copyright (c) 2016 Susisu
 */

/**
 * @module command
 */

"use strict";

function endModule() {
    module.exports = Object.freeze({
        Argument,
        OptionalArgument,
        CommandBase,
        Command
    });
}

/**
 * An instance of the `Argument` class represents a (required) argument of command.
 * @static
 */
class Argument {
    /**
     * Creates a new `Argument` instance.
     * @param {string} name A string used in placeholder.
     * @param {Function} reader A function which reads value given as argument.
     * @throws {Error} `name` is not a string.
     * @throws {Error} `reader` is not a function.
     */
    constructor(name, reader) {
        if (typeof name !== "string") {
            throw new Error("name must be a string");
        }
        if (typeof reader !== "function") {
            throw new Error("reader must be a function");
        }
        this.name   = name;
        this.reader = reader;
    }

    /**
     * Returns if the argument is required.
     * This returns always `true` (i.e. an instance of `Argument` is always required).
     * @returns {boolean} `true`.
     */
    isRequired() {
        return true;
    }

    /**
     * Returns a string which is used as a placeholder in command description.
     * @returns {string} A string which is used as a placeholder.
     */
    toPlaceholder() {
        return `<${this.name}>`;
    }

    /**
     * Returns the default value, which is used when the argument is not specified.
     * @throws {Error} No default value for a required argument.
     */
    getDefaultValue() {
        throw new Error("No default value");
    }
}

/**
 * An instance of the `OptionalArgument` class represents an optional argument of command with a default value.
 * @static
 * @extends {module:command.Argument}
 */
class OptionalArgument extends Argument {
    /**
     * Creates a new `OptionalArgument` instance.
     * @param {string} name A string used in placeholder.
     * @param defaultVal The default value, which is used when the argument is not specified.
     * @param {Function} reader A function which reads value given as argument.
     * @throws {Error} `name` is not a string.
     * @throws {Error} `reader` is not a function.
     */
    constructor(name, defaultVal, reader) {
        super(name, reader);
        this.defaultVal = defaultVal;
    }

    /**
     * Returns if the argument is required.
     * This returns always `false` (i.e. an instance of `OptionalArgument` is always not required).
     * @returns {boolean} `false`.
     */
    isRequired() {
        return false;
    }

    /**
     * Returns a string which is used as a placeholder in command description.
     * @returns {string} A string which is used as a placeholder.
     */
    toPlaceholder() {
        return `[${this.name}]`;
    }

    /**
     * Returns the default value, which is used when the argument is not specified.
     * @returns The default value specified at the constructor.
     */
    getDefaultValue() {
        return this.defaultVal;
    }
}

/**
 * The `CommandBase` class is the base class of commands.
 * @static
 */
class CommandBase {
    /**
     * Creates an instance of `CommandBase`.
     */
    constructor() {
    }

    /**
     * Parse `argv` and run action associated with the command.
     * @param {module:output.Output} out Output target.
     * @param {string[]} argv Command-line arguments.
     * @throws {Error} Not implemented.
     */
    run(out, argv) {
        throw new Error("not implemented");
    }
}

/**
 * An instance of the `Command` class represents an ordinary command.
 * @extends module:command.CommandBase
 * @static
 */
class Command extends CommandBase {
    /**
     * Creates an instance of `Command`.
     * @param {string} desc
     * @param {module:command.Argument[]} args
     * @param {module:option.Option[]} opts
     * @param {Function} action
     */
    constructor(desc, args, opts, action) {
        super();
        this.desc   = desc;
        this.args   = args;
        this.opts   = opts;
        this.action = action;
    }
}

endModule();
<commit_msg>Fix Argument constructors does not throw TypeError<commit_after>/*
 * Optics / command.js
 * copyright (c) 2016 Susisu
 */

/**
 * @module command
 */

"use strict";

function endModule() {
    module.exports = Object.freeze({
        Argument,
        OptionalArgument,
        CommandBase,
        Command
    });
}

/**
 * An instance of the `Argument` class represents a (required) argument of command.
 * @static
 */
class Argument {
    /**
     * Creates a new `Argument` instance.
     * @param {string} name A string used in placeholder.
     * @param {Function} reader A function which reads value given as argument.
     * @throws {TypeError} `name` is not a string.
     * @throws {TypeError} `reader` is not a function.
     */
    constructor(name, reader) {
        if (typeof name !== "string") {
            throw new TypeError("name must be a string");
        }
        if (typeof reader !== "function") {
            throw new TypeError("reader must be a function");
        }
        this.name   = name;
        this.reader = reader;
    }

    /**
     * Returns if the argument is required.
     * This returns always `true` (i.e. an instance of `Argument` is always required).
     * @returns {boolean} `true`.
     */
    isRequired() {
        return true;
    }

    /**
     * Returns a string which is used as a placeholder in command description.
     * @returns {string} A string which is used as a placeholder.
     */
    toPlaceholder() {
        return `<${this.name}>`;
    }

    /**
     * Returns the default value, which is used when the argument is not specified.
     * @throws {Error} No default value for a required argument.
     */
    getDefaultValue() {
        throw new Error("No default value");
    }
}

/**
 * An instance of the `OptionalArgument` class represents an optional argument of command with a default value.
 * @static
 * @extends {module:command.Argument}
 */
class OptionalArgument extends Argument {
    /**
     * Creates a new `OptionalArgument` instance.
     * @param {string} name A string used in placeholder.
     * @param defaultVal The default value, which is used when the argument is not specified.
     * @param {Function} reader A function which reads value given as argument.
     * @throws {Error} `name` is not a string.
     * @throws {Error} `reader` is not a function.
     */
    constructor(name, defaultVal, reader) {
        super(name, reader);
        this.defaultVal = defaultVal;
    }

    /**
     * Returns if the argument is required.
     * This returns always `false` (i.e. an instance of `OptionalArgument` is always not required).
     * @returns {boolean} `false`.
     */
    isRequired() {
        return false;
    }

    /**
     * Returns a string which is used as a placeholder in command description.
     * @returns {string} A string which is used as a placeholder.
     */
    toPlaceholder() {
        return `[${this.name}]`;
    }

    /**
     * Returns the default value, which is used when the argument is not specified.
     * @returns The default value specified at the constructor.
     */
    getDefaultValue() {
        return this.defaultVal;
    }
}

/**
 * The `CommandBase` class is the base class of commands.
 * @static
 */
class CommandBase {
    /**
     * Creates an instance of `CommandBase`.
     */
    constructor() {
    }

    /**
     * Parse `argv` and run action associated with the command.
     * @param {module:output.Output} out Output target.
     * @param {string[]} argv Command-line arguments.
     * @throws {Error} Not implemented.
     */
    run(out, argv) {
        throw new Error("not implemented");
    }
}

/**
 * An instance of the `Command` class represents an ordinary command.
 * @extends module:command.CommandBase
 * @static
 */
class Command extends CommandBase {
    /**
     * Creates an instance of `Command`.
     * @param {string} desc
     * @param {module:command.Argument[]} args
     * @param {module:option.Option[]} opts
     * @param {Function} action
     */
    constructor(desc, args, opts, action) {
        super();
        this.desc   = desc;
        this.args   = args;
        this.opts   = opts;
        this.action = action;
    }
}

endModule();
<|endoftext|>


<commit_before>const PACKET_TYPES = Object.create(null); // no Map = no polyfill
PACKET_TYPES["open"] = "0";
PACKET_TYPES["close"] = "1";
PACKET_TYPES["ping"] = "2";
PACKET_TYPES["pong"] = "3";
PACKET_TYPES["message"] = "4";

const PACKET_TYPES_REVERSE = Object.create(null);
Object.keys(PACKET_TYPES).forEach(key => {
  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
});

const ERROR_PACKET = { type: "error", data: "parser error" };

module.exports = {
  PACKET_TYPES,
  PACKET_TYPES_REVERSE,
  ERROR_PACKET
};
<commit_msg>feat: restore the upgrade mechanism<commit_after>const PACKET_TYPES = Object.create(null); // no Map = no polyfill
PACKET_TYPES["open"] = "0";
PACKET_TYPES["close"] = "1";
PACKET_TYPES["ping"] = "2";
PACKET_TYPES["pong"] = "3";
PACKET_TYPES["message"] = "4";
PACKET_TYPES["upgrade"] = "5";
PACKET_TYPES["noop"] = "6";

const PACKET_TYPES_REVERSE = Object.create(null);
Object.keys(PACKET_TYPES).forEach(key => {
  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
});

const ERROR_PACKET = { type: "error", data: "parser error" };

module.exports = {
  PACKET_TYPES,
  PACKET_TYPES_REVERSE,
  ERROR_PACKET
};
<|endoftext|>


<commit_before>"use strict";

const path = require('path');
const readFileSync = require('fs').readFileSync;
const extend = require('extend');
const requestP = require('request-promise');
const pkg = require('./package');

// Routes definition
const ROUTES = JSON.parse(readFileSync(path.join(__dirname, '/assets/routes.json'), 'utf-8'));

// Default configuration options
const DEFAULT_OPTIONS = {
	'baseUrl': 'https://api.github.com',
	'headers': {
		'User-Agent': 'github-api-simple v' + pkg.version + ' [nodejs] [https://github.com/MichielvdVelde/github-api-simple]'
	},
	'json': true
};

/**
 *
*/
let GithubService = function(options) {
	this._options = extend(true, DEFAULT_OPTIONS, options);

	let self = this;
	let buildMethod = function(namespace, route) {
		if(!GithubService.prototype[namespace])
			GithubService.prototype[namespace] = {};

		GithubService.prototype[namespace][route.method] = function() {
			let options = self._options;
			let argsRange = arguments.length;
			if(typeof arguments[arguments.length-1] == 'object') {
				argsRange = arguments.length-1;
				options = extend(true, options, arguments[arguments.length-1]);
			}
			options.uri = route.uri;
			let vars = Array.prototype.slice.call(arguments, 0, argsRange);
			for(let v of vars) {
				options.uri = options.uri.replace('%s', v);
			}
			return requestP(options);
		};
	};

	for(let namespace in ROUTES) {
		for(let route of ROUTES[namespace]) {
			buildMethod(namespace, route);
		}
	}
};

exports = module.exports = GithubService;
<commit_msg>Drop fs and .readFileSync() to support Browserify<commit_after>"use strict";

const path = require('path');
const extend = require('extend');
const requestP = require('request-promise');
const pkg = require('./package');

// Routes definition
const ROUTES = require('./assets/routes.json');

// Default configuration options
const DEFAULT_OPTIONS = {
	'baseUrl': 'https://api.github.com',
	'headers': {
		'User-Agent': 'github-api-simple v' + pkg.version + ' [nodejs] [https://github.com/MichielvdVelde/github-api-simple]'
	},
	'json': true
};

/**
 *
*/
let GithubService = function(options) {
	this._options = extend(true, DEFAULT_OPTIONS, options);

	let self = this;
	let buildMethod = function(namespace, route) {
		if(!GithubService.prototype[namespace])
			GithubService.prototype[namespace] = {};

		GithubService.prototype[namespace][route.method] = function() {
			let options = self._options;
			let argsRange = arguments.length;
			if(typeof arguments[arguments.length-1] == 'object') {
				argsRange = arguments.length-1;
				options = extend(true, options, arguments[arguments.length-1]);
			}
			options.uri = route.uri;
			let vars = Array.prototype.slice.call(arguments, 0, argsRange);
			for(let v of vars) {
				options.uri = options.uri.replace('%s', v);
			}
			return requestP(options);
		};
	};

	for(let namespace in ROUTES) {
		for(let route of ROUTES[namespace]) {
			buildMethod(namespace, route);
		}
	}
};

exports = module.exports = GithubService;
<|endoftext|>


<commit_before>'use strict';

var sequence  = require('es5-ext/lib/Function/sequence')
  , curry     = require('es5-ext/lib/Function/curry')
  , bcall     = require('es5-ext/lib/Function/bind-call')
  , flog      = require('es5-ext/lib/Function/log')
  , peek      = require('es5-ext/lib/List/peek').call
  , indent    = bcall(curry(require('es5-ext/lib/String/indent').call(' '),
		17, true))
  , format    = require('es5-ext/lib/Date/format')('%H:%M:%S.%L ').call
  , duration  = require('es5-ext/lib/Date/duration').call
  , dpad      = require('es5-ext/lib/String/pad').call(' ', 12).call
  , interval  = require('clock/lib/interval')

  , write     = process.stdout.write.bind(process.stdout)

  , clc       = require('cli-color')
  , ctrim     = require('cli-color/lib/trim')
  , cthrobber = require('cli-color/lib/throbber')
  , lerror    = clc.magenta
  , lfail     = clc.red
  , lpass     = clc.green
  , lsummary  = clc.cyan

  , o;

o = {
	init: function (options) {
		this.mode = options.a ? 2 : (options.m ? 0 : 1);
		this.passed = 0;
		this.failed = 0;
		this.errored = 0;
		this.started = new Date;
		this.writeLog = [];
		this.write = flog(write, this.writeLog);
		cthrobber(this.progress = interval(200, true));
		return this;
	},
	atNewLine: function () {
		return !this.writeLog.length ||
			peek(ctrim(peek(this.writeLog)[0])) === '\n';
	},
	break: function () {
		this.progress.restart();
		if (!this.atNewLine() && this.mode) {
			this.write('\n');
		}
	},
	pass: function (path, name) {
		++this.passed;
		this.progress.restart();
		if (this.mode === 2) {
			this.write(lpass(indent(format(new Date) + ' ✓  ' + name + '\n')));
		} else {
			this.write(lpass(this.atNewLine() ? (format(new Date) + ' ✓  '
				+ ((path && this.mode) ? path + ' ' : '') + '.') : '.'));
		}
	},
	fail: function (path, name, e) {
		var s, o;
		++this.failed;
		this.progress.restart();
		if (!this.atNewLine()) {
			this.write('\n');
		}
		s = format(new Date) + ' ✗  ' + name + '\n';
		if (e.operator) {
			if (e.operator !== 'throws') {
				s += 'Expected: ' + e.expected + '\n' +
					'Actual:   ' + e.actual + '\n';
			}
			s += 'Operator: ' + e.operator + '\n';
		} else {
			s += (e.stack || e) + '\n';
		}
		this.write(lfail(indent(s)));
	},
	error: function (path, name, e) {
		++this.errored;
		this.progress.restart();
		if (!this.atNewLine()) {
			this.write('\n');
		}
		name = name ? name : path;
		this.write(lerror(indent(format(new Date) + ' -  '
			+ (name ? name + '\n' : '') + (e.stack || e)) + '\n'));
	},
	end: function () {
		var s, all = this.passed + this.failed + this.errored;
		this.progress.stop();
		if (!this.atNewLine()) {
			this.write('\n');
		}
		this.write('\n');
		if (!all) {
			this.write(lsummary('No tests run\n\n'));
		} else {
			this.write(lsummary(dpad(duration(this.started, new Date).toString())
				+ '     '));
			s = [];
			s.push(clc.green(this.passed + ' Ok [' +
				Math.round((this.passed/all)*100) + '%]'));
			if (this.failed) {
				s.push(clc.red(this.failed + ' Failed'));
			}
			if (this.errored) {
				s.push(clc.magenta(this.errored + ' Errors'));
			}
			this.write(s.join('  ') + '\n\n');
		}
	}
};

module.exports = function (options) {
	return Object.create(o).init(options || {});
};
<commit_msg>Better support for different assert operators<commit_after>'use strict';

var sequence  = require('es5-ext/lib/Function/sequence')
  , curry     = require('es5-ext/lib/Function/curry')
  , bcall     = require('es5-ext/lib/Function/bind-call')
  , flog      = require('es5-ext/lib/Function/log')
  , peek      = require('es5-ext/lib/List/peek').call
  , indent    = bcall(curry(require('es5-ext/lib/String/indent').call(' '),
		17, true))
  , format    = require('es5-ext/lib/Date/format')('%H:%M:%S.%L ').call
  , duration  = require('es5-ext/lib/Date/duration').call
  , dpad      = require('es5-ext/lib/String/pad').call(' ', 12).call
  , interval  = require('clock/lib/interval')

  , write     = process.stdout.write.bind(process.stdout)

  , clc       = require('cli-color')
  , ctrim     = require('cli-color/lib/trim')
  , cthrobber = require('cli-color/lib/throbber')
  , lerror    = clc.magenta
  , lfail     = clc.red
  , lpass     = clc.green
  , lsummary  = clc.cyan

  , o;

o = {
	init: function (options) {
		this.mode = options.a ? 2 : (options.m ? 0 : 1);
		this.passed = 0;
		this.failed = 0;
		this.errored = 0;
		this.started = new Date;
		this.writeLog = [];
		this.write = flog(write, this.writeLog);
		cthrobber(this.progress = interval(200, true));
		return this;
	},
	atNewLine: function () {
		return !this.writeLog.length ||
			peek(ctrim(peek(this.writeLog)[0])) === '\n';
	},
	break: function () {
		this.progress.restart();
		if (!this.atNewLine() && this.mode) {
			this.write('\n');
		}
	},
	pass: function (path, name) {
		++this.passed;
		this.progress.restart();
		if (this.mode === 2) {
			this.write(lpass(indent(format(new Date) + ' ✓  ' + name + '\n')));
		} else {
			this.write(lpass(this.atNewLine() ? (format(new Date) + ' ✓  '
				+ ((path && this.mode) ? path + ' ' : '') + '.') : '.'));
		}
	},
	fail: function (path, name, e) {
		var s, o;
		++this.failed;
		this.progress.restart();
		if (!this.atNewLine()) {
			this.write('\n');
		}
		s = format(new Date) + ' ✗  ' + name + '\n';
		if (e.operator) {
			if (e.hasOwnProperty('expected')) {
				s += 'Expected: ' + e.expected + '\n';
			}
			if (e.hasOwnProperty('actual')) {
				s += 'Actual:   ' + e.actual + '\n';
			}
			s += 'Operator: ' + e.operator + '\n';
		} else {
			s += (e.stack || e) + '\n';
		}
		this.write(lfail(indent(s)));
	},
	error: function (path, name, e) {
		++this.errored;
		this.progress.restart();
		if (!this.atNewLine()) {
			this.write('\n');
		}
		name = name ? name : path;
		this.write(lerror(indent(format(new Date) + ' -  '
			+ (name ? name + '\n' : '') + (e.stack || e)) + '\n'));
	},
	end: function () {
		var s, all = this.passed + this.failed + this.errored;
		this.progress.stop();
		if (!this.atNewLine()) {
			this.write('\n');
		}
		this.write('\n');
		if (!all) {
			this.write(lsummary('No tests run\n\n'));
		} else {
			this.write(lsummary(dpad(duration(this.started, new Date).toString())
				+ '     '));
			s = [];
			s.push(clc.green(this.passed + ' Ok [' +
				Math.round((this.passed/all)*100) + '%]'));
			if (this.failed) {
				s.push(clc.red(this.failed + ' Failed'));
			}
			if (this.errored) {
				s.push(clc.magenta(this.errored + ' Errors'));
			}
			this.write(s.join('  ') + '\n\n');
		}
	}
};

module.exports = function (options) {
	return Object.create(o).init(options || {});
};
<|endoftext|>


<commit_before>'use strict';

var EventEmitter = require('events').EventEmitter,
    shien = require('shien'),

    Request = require('./request').Request,
    Response = require('./response').Response;

var Context = exports.Context = function (req, res) {
    EventEmitter.call(this);

    this.req = req;
    this.res = res;

    this.request = new Request(this);
    this.response = new Response(this);
};

var proto = Context.prototype = new function () {

    shien.assign(this, EventEmitter.prototype);

    this.next = function (err) {
        if (!err) {
            return this.next;
        }

        if (!(this instanceof this.next)) {
            return new this.next;
        }

        this.error = err;
    };

    this.throw = function (err) {
        if (typeof err === 'number') {
            err = new Error('Bubu gà vãi!');
        }

        throw err;
    };

};

Object.defineProperty(proto, 'url', {
    get: function () {
        return this.req.url;
    },
    set: function (value) {
        return (this.req.url = value);
    }
});

Object.defineProperty(proto, 'originalUrl', {
    get: function () {
        return this.req.originalUrl;
    },
    set: function (value) {
        return (this.req.originalUrl = value);
    }
});

Object.defineProperty(proto, 'path', {
    get: function () {
        return this.req.path;
    }
});
<commit_msg>Add `method` property from `req` to `context`<commit_after>'use strict';

var EventEmitter = require('events').EventEmitter,
    shien = require('shien'),

    Request = require('./request').Request,
    Response = require('./response').Response;

var Context = exports.Context = function (req, res) {
    EventEmitter.call(this);

    this.req = req;
    this.res = res;

    this.request = new Request(this);
    this.response = new Response(this);
};

var proto = Context.prototype = new function () {

    shien.assign(this, EventEmitter.prototype);

    this.next = function (err) {
        if (!err) {
            return this.next;
        }

        if (!(this instanceof this.next)) {
            return new this.next;
        }

        this.error = err;
    };

    this.throw = function (err) {
        if (typeof err === 'number') {
            err = new Error('Bubu gà vãi!');
        }

        throw err;
    };

};

Object.defineProperty(proto, 'method', {
    get: function () {
        return this.req.method;
    },
    set: function (value) {
        return (this.req.method = value);
    }
});

Object.defineProperty(proto, 'url', {
    get: function () {
        return this.req.url;
    },
    set: function (value) {
        return (this.req.url = value);
    }
});

Object.defineProperty(proto, 'originalUrl', {
    get: function () {
        return this.req.originalUrl;
    },
    set: function (value) {
        return (this.req.originalUrl = value);
    }
});

Object.defineProperty(proto, 'path', {
    get: function () {
        return this.req.path;
    }
});
<|endoftext|>


<commit_before>var zlib = require('zlib'),
    mapnik = require('mapnik'),
    termops = require('./util/termops'),
    feature = require('./util/feature'),
    ops = require('./util/ops'),
    sm = new (require('sphericalmercator'))(),
    queue = require('queue-async'),
    Locking = require('./util/locking'),
    addressCluster = require('./pure/addresscluster');
    applyaddress = require('./pure/applyaddress');

// Not only do we scan the exact point matched by a latitude, longitude
// pair, we also hit the 8 points that surround it as a rectangle.
var scanDirections = [
    [0, 0], [0,-1], [0, 1],
    [-1,1], [-1,0], [-1,-1],
    [1,-1], [1, 0], [1, 1]
];

// Returns a hierarchy of features ("context") for a given lon, lat pair.
//
// This is used for reverse geocoding: given a point, it returns possible
// regions that contain it.
//
// @param {Object} geocoder: geocoder instance
// @param {Float} lon: input longitude
// @param {Float} lat: input latitude
// @param {String} maxidx: optional type of the most detailed feature to return
// @param {String} full: boolean of whether to do a full load of all features
// @param {Function} callback
module.exports = function(geocoder, lon, lat, maxidx, full, callback) {
    var context = [];
    var indexes = geocoder.indexes;
    var types = Object.keys(indexes);
    types = types.slice(0, typeof maxidx === 'number' ? maxidx : types.length);

    // No-op context.
    if (!types.length) return callback(null, context);

    var q = queue();
    types.forEach(function(type) {
        var source = indexes[type];
        var bounds = source._geocoder.bounds;

        if (lat >= bounds[1] && lat <= bounds[3] && lon >= bounds[0] && lon <= bounds[2])
            q.defer(contextVector, source, lon, lat, full);
    });

    q.awaitAll(function(err, res) {
        if (err) return callback(err);
        res = res.reverse().filter(identity);
        callback(null, res);
    });
};

module.exports.contextVector = contextVector;

// For each context type, load a representative tile, look around the
// pixel we've identified, and if we find a feature, add it to the `context`
// array under an array index that represents the position of the context
// in imaginary z-space (country, town, place, etc). When there are no more
// to do, return that array, filtered of nulls and reversed.
function contextVector(source, lon, lat, full, callback) {
    var xyz = sm.xyz([lon, lat, lon, lat], source._geocoder.maxzoom);
    var z = source._geocoder.maxzoom;
    var x = xyz.minX;
    var y = xyz.minY;
    var id = source._geocoder.group || source._geocoder.id;
    var ckey = id + '/' + z + '/' + x + '/' + y;
    var lock = Locking(ckey, query);

    // Load the potential tile in which a match would occur.
    lock(function(unlock) {
        source.getTile(z, x, y, function(err, zpbf) {
            if (err && err.message !== 'Tile does not exist') return unlock(err);
            if (!zpbf) return unlock(null, false);

            var compression = false;
            if (zpbf[0] == 0x78 && zpbf[1] == 0x9C) {
                compression = 'inflate';
            } else if (zpbf[0] == 0x1F && zpbf[1] == 0x8B) {
                compression = 'gunzip';
            }
            if (!compression) return unlock(new Error('Could not detect compression of vector tile'));

            zlib[compression](zpbf, function(err, pbf) {
                if (err) return unlock(err);
                if (pbf.length === 0) return unlock(null, false);
                var vt = new mapnik.VectorTile(z, x, y);
                try {
                    vt.setData(pbf);
                } catch (err) {
                    return unlock(err);
                }
                vt.parse(function(err) {
                    if (err) return unlock(err);
                    return unlock(null, vt);
                });
            });
        });
    });

    // For a loaded vector tile, query for features at the lon,lat.
    function query(err, vt) {
        if (err) return callback(err);
        if (!vt) return callback(null, false);

        // Uses a 50m (web mercator units) tolerance.
        vt.query(lon, lat, {
            tolerance: 50,
            layer: source._geocoder.geocoder_layer
        }, function(err, results) {
            if (err) return callback(err);
            if (!results || !results.length) return callback(null, false);

            // Exclude features with a negative score.
            for (var i = 0; i < results.length; i++) {
                var attr = results[i].attributes();
                if (attr._score < 0) continue;
                attr._id = results[i].id();
                return loadFeature(source, attr, full, [lon,lat], callback);
            }

            // No matching features found.
            return callback(null, false);
        });
    }
}

// Load the full feature from geocoding data if needed, otherwise create
// a light reference with id + text.
function loadFeature(source, feat, full, query, callback) {
    var dbname = source._geocoder.name;
    var dbidx = source._geocoder.idx;
    if (!full) {
        var loaded = {};
        loaded._extid = dbname + '.' + feat._id;
        loaded._tmpid = dbidx * 1e8 + termops.feature(feat._id);
        loaded._text = feat._text || feat.name || feat.search;
        return callback(null, loaded._text ? loaded : false);
    }

    feature.getFeature(source, termops.feature(feat._id), function(err, data) {
        if (err) return callback(err);
        if (!data || !data[feat._id]) return callback();
        var loaded = data[feat._id];
        loaded._extid = dbname + '.' + feat._id;
        loaded._tmpid = dbidx * 1e8 + termops.feature(feat._id);

        if (source._geocoder.geocoder_address && loaded._cluster)
            loaded = addressCluster.reverse(loaded, query);
        else if (source._geocoder.geocoder_address && loaded._rangetype)
            loaded = applyaddress.reverse(loaded, query);

        return callback(null, loaded);
    });
}

function identity(v) { return v; }
<commit_msg>Support geojson properties.id<commit_after>var zlib = require('zlib'),
    mapnik = require('mapnik'),
    termops = require('./util/termops'),
    feature = require('./util/feature'),
    ops = require('./util/ops'),
    sm = new (require('sphericalmercator'))(),
    queue = require('queue-async'),
    Locking = require('./util/locking'),
    addressCluster = require('./pure/addresscluster');
    applyaddress = require('./pure/applyaddress');

// Not only do we scan the exact point matched by a latitude, longitude
// pair, we also hit the 8 points that surround it as a rectangle.
var scanDirections = [
    [0, 0], [0,-1], [0, 1],
    [-1,1], [-1,0], [-1,-1],
    [1,-1], [1, 0], [1, 1]
];

// Returns a hierarchy of features ("context") for a given lon, lat pair.
//
// This is used for reverse geocoding: given a point, it returns possible
// regions that contain it.
//
// @param {Object} geocoder: geocoder instance
// @param {Float} lon: input longitude
// @param {Float} lat: input latitude
// @param {String} maxidx: optional type of the most detailed feature to return
// @param {String} full: boolean of whether to do a full load of all features
// @param {Function} callback
module.exports = function(geocoder, lon, lat, maxidx, full, callback) {
    var context = [];
    var indexes = geocoder.indexes;
    var types = Object.keys(indexes);
    types = types.slice(0, typeof maxidx === 'number' ? maxidx : types.length);

    // No-op context.
    if (!types.length) return callback(null, context);

    var q = queue();
    types.forEach(function(type) {
        var source = indexes[type];
        var bounds = source._geocoder.bounds;

        if (lat >= bounds[1] && lat <= bounds[3] && lon >= bounds[0] && lon <= bounds[2])
            q.defer(contextVector, source, lon, lat, full);
    });

    q.awaitAll(function(err, res) {
        if (err) return callback(err);
        res = res.reverse().filter(identity);
        callback(null, res);
    });
};

module.exports.contextVector = contextVector;

// For each context type, load a representative tile, look around the
// pixel we've identified, and if we find a feature, add it to the `context`
// array under an array index that represents the position of the context
// in imaginary z-space (country, town, place, etc). When there are no more
// to do, return that array, filtered of nulls and reversed.
function contextVector(source, lon, lat, full, callback) {
    var xyz = sm.xyz([lon, lat, lon, lat], source._geocoder.maxzoom);
    var z = source._geocoder.maxzoom;
    var x = xyz.minX;
    var y = xyz.minY;
    var id = source._geocoder.group || source._geocoder.id;
    var ckey = id + '/' + z + '/' + x + '/' + y;
    var lock = Locking(ckey, query);

    // Load the potential tile in which a match would occur.
    lock(function(unlock) {
        source.getTile(z, x, y, function(err, zpbf) {
            if (err && err.message !== 'Tile does not exist') return unlock(err);
            if (!zpbf) return unlock(null, false);

            var compression = false;
            if (zpbf[0] == 0x78 && zpbf[1] == 0x9C) {
                compression = 'inflate';
            } else if (zpbf[0] == 0x1F && zpbf[1] == 0x8B) {
                compression = 'gunzip';
            }
            if (!compression) return unlock(new Error('Could not detect compression of vector tile'));

            zlib[compression](zpbf, function(err, pbf) {
                if (err) return unlock(err);
                if (pbf.length === 0) return unlock(null, false);
                var vt = new mapnik.VectorTile(z, x, y);
                try {
                    vt.setData(pbf);
                } catch (err) {
                    return unlock(err);
                }
                vt.parse(function(err) {
                    if (err) return unlock(err);
                    return unlock(null, vt);
                });
            });
        });
    });

    // For a loaded vector tile, query for features at the lon,lat.
    function query(err, vt) {
        if (err) return callback(err);
        if (!vt) return callback(null, false);

        // Uses a 50m (web mercator units) tolerance.
        vt.query(lon, lat, {
            tolerance: 50,
            layer: source._geocoder.geocoder_layer
        }, function(err, results) {
            if (err) return callback(err);
            if (!results || !results.length) return callback(null, false);

            // Exclude features with a negative score.
            for (var i = 0; i < results.length; i++) {
                var attr = results[i].attributes();
                if (attr._score < 0) continue;

                //If geojson has an id in properties use that otherwise use VT id
                attr._id = attr.id || results[i].id();
                return loadFeature(source, attr, full, [lon,lat], callback);
            }

            // No matching features found.
            return callback(null, false);
        });
    }
}

// Load the full feature from geocoding data if needed, otherwise create
// a light reference with id + text.
function loadFeature(source, feat, full, query, callback) {
    var dbname = source._geocoder.name;
    var dbidx = source._geocoder.idx;
    if (!full) {
        var loaded = {};
        loaded._extid = dbname + '.' + feat._id;
        loaded._tmpid = dbidx * 1e8 + termops.feature(feat._id);
        loaded._text = feat._text || feat.name || feat.search;
        return callback(null, loaded._text ? loaded : false);
    }

    feature.getFeature(source, termops.feature(feat._id), function(err, data) {
        if (err) return callback(err);
        if (!data || !data[feat._id]) return callback();
        var loaded = data[feat._id];
        loaded._extid = dbname + '.' + feat._id;
        loaded._tmpid = dbidx * 1e8 + termops.feature(feat._id);

        if (source._geocoder.geocoder_address && loaded._cluster)
            loaded = addressCluster.reverse(loaded, query);
        else if (source._geocoder.geocoder_address && loaded._rangetype)
            loaded = applyaddress.reverse(loaded, query);

        return callback(null, loaded);
    });
}

function identity(v) { return v; }
<|endoftext|>


<commit_before>// Copyright 2012 Joyent, Inc.  All rights reserved.

var assert = require('assert-plus');
var carrier = require('carrier');

///--- Globals

var BLOCK_SIZE = 4096;
var KB_PER_BLOCK = BLOCK_SIZE / 1024;

///--- API

// Process a manta object's json record.
//
// aggregation: the map used for aggregation
// log: logger
// record: a record to be aggregated
function mapFunction(opts) {
        assert.object(opts, 'options');
        assert.object(opts.aggregation, 'options.aggregation');
        assert.object(opts.log, 'options.log');
        assert.object(opts.record, 'options.record');

        var aggr = opts.aggregation;
        var log = opts.log;
        var obj = opts.record;
        var owner = obj.owner;
        // The createdFrom property distinguished links from objects
        var isLink = obj.createdFrom;
        var size = Math.ceil(obj.contentLength / BLOCK_SIZE) * KB_PER_BLOCK;
        var copies = obj.sharks.length;

        log.debug({
                aggregation: aggr,
                record: obj
        }, 'mapFunction: entered');

        aggr[obj.owner] = aggr[owner] || {
                numKb: 0,
                numKeys: 0
        };

        aggr[owner].numKb += isLink ? 0 : (size * copies);
        aggr[owner].numKeys++;

        log.debug({
                aggregation: aggr
        }, 'mapFunction: done');

        return (aggr);
}

// Aggregate a mapper's output.
//
// aggregation: the map used for aggregation
// log: logger
// record: a record from a map phase
function reduceFunction(opts) {
        assert.object(opts, 'options');
        assert.object(opts.aggregation, 'options.aggregation');
        assert.object(opts.log, 'options.log');
        assert.object(opts.record, 'options.record');

        var aggr = opts.aggregation;
        var log = opts.log;
        var obj = opts.record;
        var owner = obj.owner;

        log.debug({
                aggregation: aggr,
                record: obj
        }, 'reduceFunction: entered');

        aggr[obj.owner] = aggr[owner] || {
                numKb: 0,
                numKeys: 0
        };

        aggr[owner].numKb += obj.numKb;
        aggr[owner].numKeys += obj.numKeys;

        log.debug({
                aggregation: aggr
        }, 'reduceFunction: done');

        return (aggr);
}

// Takes a javascript object and reformats it into a streaming json format
//
// aggregation: the map to format into streaming json
// log: logger
// outputStream: a writable stream to output to, e.g. stdout
function format(opts) {
        assert.object(opts, 'options');
        assert.object(opts.aggregation, 'options.aggregation');
        assert.object(opts.log, 'options.log');
        assert.object(opts.outputStream, 'options.outputStream');

        var agg = opts.aggregation;
        var log = opts.log;
        var stream = opts.outputStream;

        var template = {
                owner: undefined,
                numKb: undefined,
                numKeys: undefined
        };

        log.debug('format: entered');

        Object.keys(agg).forEach(function (key) {
                template.owner = key;
                template.numKb = agg[key].numKb;
                template.numKeys = agg[key].numKeys;
                stream.write(JSON.stringify(template) + '\n');
        });

        log.debug('format: done');
}

// Aggregates records
//
// stream: a readable stream, e.g. stdin
// aggregation: an empty object that will be used for aggregation
// log: logger
// aggregationFunction: the function that contains the logic on how to
//      aggregate each record, viz. mapFunction, reduceFunction
// callback: callback function to call once aggregation is done
function aggregate(opts) {
        assert.object(opts, 'options');
        assert.object(opts.stream, 'options.stream');
        assert.object(opts.aggregation, 'options.aggregation');
        assert.object(opts.log, 'options.log');
        assert.func(opts.aggregationFunction, 'options.aggregationFunction');
        assert.func(opts.callback, 'options.callback');

        var aggr = opts.aggregation;
        var stream = opts.stream;
        var log = opts.log;
        var aggFunction = opts.aggregationFunction;
        var callback = opts.callback;

        var carry = carrier.carry(stream);
        carry.on('line', function onLine(line) {
                var record;

                try {
                        record = JSON.parse(line);
                        aggFunction({
                                aggregation: aggr,
                                log: log,
                                record: record
                        });

                } catch (e) {
                        log.fatal(e, 'invalid line');
                }
        });

        carry.once('end', function returnResults() {
                callback();
        });
}

///--- Exports

module.exports = {

        mapFunction: mapFunction,
        reduceFunction: reduceFunction,
        format: format,
        aggregate: aggregate

};
<commit_msg>MANTA-195 \n -> \r\n<commit_after>// Copyright 2012 Joyent, Inc.  All rights reserved.

var assert = require('assert-plus');
var carrier = require('carrier');

///--- Globals

var BLOCK_SIZE = 4096;
var KB_PER_BLOCK = BLOCK_SIZE / 1024;

///--- API

// Process a manta object's json record.
//
// aggregation: the map used for aggregation
// log: logger
// record: a record to be aggregated
function mapFunction(opts) {
        assert.object(opts, 'options');
        assert.object(opts.aggregation, 'options.aggregation');
        assert.object(opts.log, 'options.log');
        assert.object(opts.record, 'options.record');

        var aggr = opts.aggregation;
        var log = opts.log;
        var obj = opts.record;
        var owner = obj.owner;
        // The createdFrom property distinguished links from objects
        var isLink = obj.createdFrom;
        var size = Math.ceil(obj.contentLength / BLOCK_SIZE) * KB_PER_BLOCK;
        var copies = obj.sharks.length;

        log.debug({
                aggregation: aggr,
                record: obj
        }, 'mapFunction: entered');

        aggr[obj.owner] = aggr[owner] || {
                numKb: 0,
                numKeys: 0
        };

        aggr[owner].numKb += isLink ? 0 : (size * copies);
        aggr[owner].numKeys++;

        log.debug({
                aggregation: aggr
        }, 'mapFunction: done');

        return (aggr);
}

// Aggregate a mapper's output.
//
// aggregation: the map used for aggregation
// log: logger
// record: a record from a map phase
function reduceFunction(opts) {
        assert.object(opts, 'options');
        assert.object(opts.aggregation, 'options.aggregation');
        assert.object(opts.log, 'options.log');
        assert.object(opts.record, 'options.record');

        var aggr = opts.aggregation;
        var log = opts.log;
        var obj = opts.record;
        var owner = obj.owner;

        log.debug({
                aggregation: aggr,
                record: obj
        }, 'reduceFunction: entered');

        aggr[obj.owner] = aggr[owner] || {
                numKb: 0,
                numKeys: 0
        };

        aggr[owner].numKb += obj.numKb;
        aggr[owner].numKeys += obj.numKeys;

        log.debug({
                aggregation: aggr
        }, 'reduceFunction: done');

        return (aggr);
}

// Takes a javascript object and reformats it into a streaming json format
//
// aggregation: the map to format into streaming json
// log: logger
// outputStream: a writable stream to output to, e.g. stdout
function format(opts) {
        assert.object(opts, 'options');
        assert.object(opts.aggregation, 'options.aggregation');
        assert.object(opts.log, 'options.log');
        assert.object(opts.outputStream, 'options.outputStream');

        var agg = opts.aggregation;
        var log = opts.log;
        var stream = opts.outputStream;

        var template = {
                owner: undefined,
                numKb: undefined,
                numKeys: undefined
        };

        log.debug('format: entered');

        Object.keys(agg).forEach(function (key) {
                template.owner = key;
                template.numKb = agg[key].numKb;
                template.numKeys = agg[key].numKeys;
                stream.write(JSON.stringify(template) + '\r\n');
        });

        log.debug('format: done');
}

// Aggregates records
//
// stream: a readable stream, e.g. stdin
// aggregation: an empty object that will be used for aggregation
// log: logger
// aggregationFunction: the function that contains the logic on how to
//      aggregate each record, viz. mapFunction, reduceFunction
// callback: callback function to call once aggregation is done
function aggregate(opts) {
        assert.object(opts, 'options');
        assert.object(opts.stream, 'options.stream');
        assert.object(opts.aggregation, 'options.aggregation');
        assert.object(opts.log, 'options.log');
        assert.func(opts.aggregationFunction, 'options.aggregationFunction');
        assert.func(opts.callback, 'options.callback');

        var aggr = opts.aggregation;
        var stream = opts.stream;
        var log = opts.log;
        var aggFunction = opts.aggregationFunction;
        var callback = opts.callback;

        var carry = carrier.carry(stream);
        carry.on('line', function onLine(line) {
                var record;

                try {
                        record = JSON.parse(line);
                        aggFunction({
                                aggregation: aggr,
                                log: log,
                                record: record
                        });

                } catch (e) {
                        log.fatal(e, 'invalid line');
                }
        });

        carry.once('end', function returnResults() {
                callback();
        });
}

///--- Exports

module.exports = {

        mapFunction: mapFunction,
        reduceFunction: reduceFunction,
        format: format,
        aggregate: aggregate

};
<|endoftext|>