<commit_before>// Define Configuration

var config = {
    // Authentication keys
    keys: [
        "12345",
        "67890"
    ],
    /**
     * Allowed IP's or ranges
     * Can use * for wildcards, *.*.*.* for no restrictions
     */
    ips: [
        "*.*.*.*"
    ],
    /**
     * SSL Config
     * Set key and cert to absolute path if SSL used, false if not
     */
    ssl: {
        key: false,
        cert: false
    },
    // Port designation
    port: 8080,
    // Base directory
    base: "example/base",
    // Default create mode
    cmode: "0755"
};

var fs = require("fs-extra"),
    restify = require("restify"),
    server;

// Determine if SSL is used
if (config.ssl.key && config.ssl.cert) {

    // Get CERT
    var https = {
        certificate: fs.readFileSync(config.ssl.cert),
        key: fs.readFileSync(config.ssl.key)
    };

    // Config server with SSL
    server = restify.createServer({
        name: "fsapi",
        certificate: https.certificate,
        key: https.key
    });

} else {

    // Config non-SSL Server
    server = restify.createServer({
        name: "fsapi"
    });

}

// Additional server config
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
server.use(restify.CORS());

// Regular Expressions
var commandRegEx = /^\/([a-zA-Z0-9_\.~-]+)\/([a-zA-Z0-9_\.~-]+)\/(.*)/,  // /{key}/{command}/{path}
    pathRegEx = /^\/([a-zA-Z0-9_\.~-]+)\/(.*)/;  // /{key}/{path}

/**
 * UnknownMethod handler
 */
function unknownMethodHandler(req, res) {
  if (req.method.toLowerCase() === 'options') {
    var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With']; // added Origin & X-Requested-With

    if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');

    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.header('Access-Control-Allow-Origin', req.headers.origin);

    return res.send(204);
  }
  else
    return res.send(new restify.MethodNotAllowedError());
}

server.on('MethodNotAllowed', unknownMethodHandler);

/**
 * Check Key (Called by checkReq)
 */
var checkKey = function (config, req) {
    // Loop through keys in config
    for (var i = 0, z = config.keys.length; i < z; i++) {
        if (config.keys[i] === req.params[0]) {
            return true;
        }
    }
    return false;
};

/**
 * Check IP (Called by checkReq)
 */

var checkIP = function (config, req) {
    var ip = req.connection.remoteAddress.split("."),
        curIP,
        b,
        block = [];
    for (var i=0, z=config.ips.length-1; i<=z; i++) {
        curIP = config.ips[i].split(".");
        b = 0;
        // Compare each block
        while (b<=3) {
            (curIP[b]===ip[b] || curIP[b]==="*") ? block[b] = true : block[b] = false;
            b++;
        }
        // Check all blocks
        if (block[0] && block[1] && block[2] && block[3]) {
            return true;
        }
    }
    return false;
};

/**
 * Check Request
 * Checks Key and IP Address
 */

var checkReq = function (config, req, res) {

    // Set access control headers
    res.header('Access-Control-Allow-Origin', '*');

    // Check key and IP
    if(!checkKey(config, req) || !checkIP(config, req)) {
        res.send(401);
        return false;
    }

    return true;
};

/**
 * Response Error
 */

var resError = function (code, raw, res) {

    var codes = {
        100: "Unknown command",
        101: "Could not list files",
        102: "Could not read file",
        103: "Path does not exist",
        104: "Could not create copy",
        105: "File does not exist",
        106: "Not a file",
        107: "Could not write to file",
        108: "Could not delete object"
    };

    res.send({ "status": "error", "code": code, "message": codes[code], "raw": raw });
    return false;

};

/**
 * Response Success
 */

var resSuccess = function (data, res) {

    res.send({ "status": "success", "data": data });

};

/**
 * Merge function
 */

var merge = function (obj1,obj2) {
    var mobj = {},
        attrname;
    for (attrname in obj1) { mobj[attrname] = obj1[attrname]; }
    for (attrname in obj2) { mobj[attrname] = obj2[attrname]; }
    return mobj;
};

/**
 * Get Base Path
 */

var getBasePath = function (path) {
    var base_path = path.split("/");

    base_path.pop();
    return base_path.join("/");
};

/**
 * Check Path
 */

var checkPath = function (path) {
    var base_path = getBasePath(path);
    return fs.existsSync(base_path);
};

/**
 * GET (Read)
 *
 * Commands:
 * dir - list contents of directory
 * file - return content of a file
 *
 */
server.get(commandRegEx, function (req, res, next) {

    // Check request
    checkReq(config, req, res);

    // Set path
    var path = config.base + "/" + req.params[2];

    switch (req.params[1]) {
        // List contents of directory
        case "dir":
            fs.readdir(path, function (err, files) {
                if (err) {
                    resError(101, err, res);
                } else {

                    // Ensure ending slash on path
                    (path.slice(-1)!=="/") ? path = path + "/" : path = path;

                    var output = {},
                        output_dirs = {},
                        output_files = {},
                        current,
                        relpath,
                        link;

                    // Function to build item for output objects
                    var createItem = function (current, relpath, type, link) {
                        return {
                            path: relpath.replace('//','/'),
                            type: type,
                            size: fs.lstatSync(current).size,
                            atime: fs.lstatSync(current).atime.getTime(),
                            mtime: fs.lstatSync(current).mtime.getTime(),
                            link: link
                        };
                    };

                    // Sort alphabetically
                    files.sort();

                    // Loop through and create two objects
                    // 1. Directories
                    // 2. Files
                    for (var i=0, z=files.length-1; i<=z; i++) {
                        current = path + files[i];
                        relpath = current.replace(config.base,"");
                        (fs.lstatSync(current).isSymbolicLink()) ? link = true : link = false;
                        if (fs.lstatSync(current).isDirectory()) {
                            output_dirs[files[i]] = createItem(current,relpath,"directory",link);
                        } else {
                            output_files[files[i]] = createItem(current,relpath,"file",link);
                        }
                    }

                    // Merge so we end up with alphabetical directories, then files
                    output = merge(output_dirs,output_files);

                    // Send output
                    resSuccess(output, res);
                }
            });
            break;

        // Return contents of requested file
        case "file":
            fs.readFile(path, "utf8", function (err, data) {
                if (err) {
                    resError(102, err, res);
                } else {
                    resSuccess(data, res);
                }
            });
            break;

        default:
            // Unknown command
            resError(100, null, res);
    }

    return next();
});

/**
 * POST (Create)
 *
 * Commands:
 * dir - creates a new directory
 * file - creates a new file
 * copy - copies a file or dirextory (to path at param "destination")
 *
 */
server.post(commandRegEx, function (req, res, next) {

    // Check request
    checkReq(config, req, res);

    // Set path
    var path = config.base + "/" + req.params[2];

    switch (req.params[1]) {

        // Creates a new directory
        case "dir":

            // Ensure base path
            if (checkPath(path)) {
                // Base path exists, create directory
                fs.mkdir(path, config.cmode, function () {
                    resSuccess(null, res);
                });
            } else {
                // Bad base path
                resError(103, null, res);
            }
            break;

        // Creates a new file
        case "file":
            // Ensure base path
            if (checkPath(path)) {
                // Base path exists, create file
                fs.openSync(path, "w");
                resSuccess(null, res);
            } else {
                // Bad base path
                resError(103, null, res);
            }
            break;

        // Copies a file or directory
        // Supply destination as full path with file or folder name at end
        // Ex: http://yourserver.com/{key}/copy/folder_a/somefile.txt, destination: /folder_b/somefile.txt
        case "copy":
            var destination = config.base + "/" + req.params.destination;
            if (checkPath(path) && checkPath(destination)) {
                fs.copy(path, destination, function(err){
                    if (err) {
                        resError(104, err, res);
                    }
                    else {
                        resSuccess(null, res);
                    }
                });
            } else {
                // Bad base path
                resError(103, null, res);
            }
            break;

        default:
            // Unknown command
            resError(100, null, res);
    }

    return next();
});

/**
 * PUT (Update)
 *
 * Commands:
 * rename - renames a file or folder (using param "name")
 * save - saves contents to a file (using param "data")
 *
 */
server.put(commandRegEx, function (req, res, next) {

    // Check request
    checkReq(config, req, res);

    // Set path
    var path = config.base + "/" + req.params[2];

    switch (req.params[1]) {

        // Rename a file or directory
        case "rename":

            var base_path = getBasePath(path);

            fs.rename(path,base_path + "/" + req.params.name, function () {
                resSuccess(null, res);
            });

            break;

        // Saves contents to a file
        case "save":

            // Make sure it exists
            if (fs.existsSync(path)) {
                // Make sure it's a file
                if (!fs.lstatSync(path).isDirectory()) {
                    // Write
                    fs.writeFile(path, req.params.data, function(err) {
                        if(err) {
                            resError(107, err, res);
                        } else {
                            resSuccess(null, res);
                        }
                    });
                } else {
                    resError(106, null, res);
                }
            } else {
                resError(105, null, res);
            }

            break;

        default:
            // Unknown command
            resError(100, null, res);
    }

    return next();

});

/**
 * DELETE
 */
server.del(pathRegEx, function (req, res, next) {

    // Check request
    checkReq(config, req, res);

    // Set path
    var path = config.base + "/" + req.params[1];

    // Make sure it exists
    if (fs.existsSync(path)) {
        // Remove file or directory
        fs.remove(path, function (err) {
            if (err) {
                resError(108, err, res);
            } else {
                resSuccess(null, res);
            }
        });
    } else {
        resError(103, null, res);
    }

    return next();

});

/**
 * START SERVER
 */
server.listen(config.port, function () {
    console.log("%s listening at %s", server.name, server.url);
});<commit_msg>fix get<commit_after>// Define Configuration

var config = {
    // Authentication keys
    keys: [
        "12345",
        "67890"
    ],
    /**
     * Allowed IP's or ranges
     * Can use * for wildcards, *.*.*.* for no restrictions
     */
    ips: [
        "*.*.*.*"
    ],
    /**
     * SSL Config
     * Set key and cert to absolute path if SSL used, false if not
     */
    ssl: {
        key: false,
        cert: false
    },
    // Port designation
    port: 8080,
    // Base directory
    base: "example/base",
    // Default create mode
    cmode: "0755"
};

var fs = require("fs-extra"),
    restify = require("restify"),
    server;

// Determine if SSL is used
if (config.ssl.key && config.ssl.cert) {

    // Get CERT
    var https = {
        certificate: fs.readFileSync(config.ssl.cert),
        key: fs.readFileSync(config.ssl.key)
    };

    // Config server with SSL
    server = restify.createServer({
        name: "fsapi",
        certificate: https.certificate,
        key: https.key
    });

} else {

    // Config non-SSL Server
    server = restify.createServer({
        name: "fsapi"
    });

}

// Additional server config
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
server.use(restify.CORS());

// Regular Expressions
var commandRegEx = /^\/([a-zA-Z0-9_\.~-]+)\/([a-zA-Z0-9_\.~-]+)\/(.*)/,  // /{key}/{command}/{path}
    pathRegEx = /^\/([a-zA-Z0-9_\.~-]+)\/(.*)/;  // /{key}/{path}

/**
 * UnknownMethod handler
 */
function unknownMethodHandler(req, res) {
  if (req.method.toLowerCase() === 'options') {
    var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With']; // added Origin & X-Requested-With

    if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');

    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.header('Access-Control-Allow-Origin', req.headers.origin);

    return res.send(204);
  }
  else
    return res.send(new restify.MethodNotAllowedError());
}

server.on('MethodNotAllowed', unknownMethodHandler);

/**
 * Check Key (Called by checkReq)
 */
var checkKey = function (config, req) {
    // Loop through keys in config
    for (var i = 0, z = config.keys.length; i < z; i++) {
        if (config.keys[i] === req.params[0]) {
            return true;
        }
    }
    return false;
};

/**
 * Check IP (Called by checkReq)
 */

var checkIP = function (config, req) {
    var ip = req.connection.remoteAddress.split("."),
        curIP,
        b,
        block = [];
    for (var i=0, z=config.ips.length-1; i<=z; i++) {
        curIP = config.ips[i].split(".");
        b = 0;
        // Compare each block
        while (b<=3) {
            (curIP[b]===ip[b] || curIP[b]==="*") ? block[b] = true : block[b] = false;
            b++;
        }
        // Check all blocks
        if (block[0] && block[1] && block[2] && block[3]) {
            return true;
        }
    }
    return false;
};

/**
 * Check Request
 * Checks Key and IP Address
 */

var checkReq = function (config, req, res) {

    // Set access control headers
    res.header('Access-Control-Allow-Origin', '*');

    // Check key and IP
    if(!checkKey(config, req) || !checkIP(config, req)) {
        res.send(401);
        return false;
    }

    return true;
};

/**
 * Response Error
 */

var resError = function (code, raw, res) {

    var codes = {
        100: "Unknown command",
        101: "Could not list files",
        102: "Could not read file",
        103: "Path does not exist",
        104: "Could not create copy",
        105: "File does not exist",
        106: "Not a file",
        107: "Could not write to file",
        108: "Could not delete object"
    };

    res.send({ "status": "error", "code": code, "message": codes[code], "raw": raw });
    return false;

};

/**
 * Response Success
 */

var resSuccess = function (data, res) {

    res.send({ "status": "success", "data": data });

};

/**
 * Merge function
 */

var merge = function (obj1,obj2) {
    var mobj = {},
        attrname;
    for (attrname in obj1) { mobj[attrname] = obj1[attrname]; }
    for (attrname in obj2) { mobj[attrname] = obj2[attrname]; }
    return mobj;
};

/**
 * Get Base Path
 */

var getBasePath = function (path) {
    var base_path = path.split("/");

    base_path.pop();
    return base_path.join("/");
};

/**
 * Check Path
 */

var checkPath = function (path) {
    var base_path = getBasePath(path);
    return fs.existsSync(base_path);
};

/**
 * GET (Read)
 *
 * Commands:
 * dir - list contents of directory
 * file - return content of a file
 *
 */
server.get(commandRegEx, function (req, res, next) {

    // Check request
    checkReq(config, req, res);

    // Set path
    var path = config.base + "/" + req.params[2];

    switch (req.params[1]) {
        // List contents of directory
        case "dir":
            fs.readdir(path, function (err, files) {
                if (err) {
                    resError(101, err, res);
                } else {

                    // Ensure ending slash on path
                    (path.slice(-1)!=="/") ? path = path + "/" : path = path;

                    var output = {},
                        output_dirs = {},
                        output_files = {},
                        current,
                        relpath,
                        link;

                    // Function to build item for output objects
                    var createItem = function (current, relpath, type, link) {
                        return {
                            path: relpath.replace('//','/'),
                            type: type,
                            size: fs.lstatSync(current).size,
                            atime: fs.lstatSync(current).atime.getTime(),
                            mtime: fs.lstatSync(current).mtime.getTime(),
                            link: link
                        };
                    };

                    // Sort alphabetically
                    files.sort();

                    // Loop through and create two objects
                    // 1. Directories
                    // 2. Files
                    for (var i=0, z=files.length-1; i<=z; i++) {
                        current = path + files[i];
                        relpath = current.replace(config.base,"");
                        (fs.lstatSync(current).isSymbolicLink()) ? link = true : link = false;
                        if (fs.lstatSync(current).isDirectory()) {
                            output_dirs[files[i]] = createItem(current,relpath,"directory",link);
                        } else {
                            output_files[files[i]] = createItem(current,relpath,"file",link);
                        }
                    }

                    // Merge so we end up with alphabetical directories, then files
                    output = merge(output_dirs,output_files);

                    // Send output
                    resSuccess(output, res);
                }
            });
            break;

        // Return contents of requested file
        case "file":
            fs.readFile(path, "utf8", function (err, data) {
                if (err) {
                    resError(102, err, res);
                } else {
                    resSuccess(data, res);
                }
            });
            break;

        default:
            // Unknown command
            resError(100, null, res);
    }

    return next();
});

/**
 * POST (Create)
 *
 * Commands:
 * dir - creates a new directory
 * file - creates a new file
 * copy - copies a file or dirextory (to path at param "destination")
 *
 */
server.post(commandRegEx, function (req, res, next) {

    // Check request
    checkReq(config, req, res);

    // Set path
    var path = config.base + "/" + req.params[2];

    switch (req.params[1]) {

        // Creates a new directory
        case "dir":

            // Ensure base path
            if (checkPath(path)) {
                // Base path exists, create directory
                fs.mkdir(path, config.cmode, function () {
                    resSuccess(null, res);
                });
            } else {
                // Bad base path
                resError(103, null, res);
            }
            break;

        // Creates a new file
        case "file":
            // Ensure base path
            if (checkPath(path)) {
                // Base path exists, create file
                fs.openSync(path, "w");
                resSuccess(null, res);
            } else {
                // Bad base path
                resError(103, null, res);
            }
            break;

        // Copies a file or directory
        // Supply destination as full path with file or folder name at end
        // Ex: http://yourserver.com/{key}/copy/folder_a/somefile.txt, destination: /folder_b/somefile.txt
        case "copy":
            var destination = config.base + "/" + req.params.destination;
            if (checkPath(path) && checkPath(destination)) {
                fs.copy(path, destination, function(err){
                    if (err) {
                        resError(104, err, res);
                    }
                    else {
                        resSuccess(null, res);
                    }
                });
            } else {
                // Bad base path
                resError(103, null, res);
            }
            break;

        default:
            // Unknown command
            resError(100, null, res);
    }

    return next();
});

/**
 * PUT (Update)
 *
 * Commands:
 * rename - renames a file or folder (using param "name")
 * save - saves contents to a file (using param "data")
 *
 */
server.put(commandRegEx, function (req, res, next) {

    // Check request
    checkReq(config, req, res);

    // Set path
    var path = config.base + "/" + req.params[2];

    switch (req.params[1]) {

        // Rename a file or directory
        case "rename":

            var base_path = getBasePath(path);

            fs.rename(path,base_path + "/" + req.params.name, function () {
                resSuccess(null, res);
            });

            break;

        // Saves contents to a file
        case "save":

            // Make sure it exists
            if (fs.existsSync(path)) {
                // Make sure it's a file
                if (!fs.lstatSync(path).isDirectory()) {
                    // Write
                    fs.writeFile(path, req.params.data, function(err) {
                        if(err) {
                            resError(107, err, res);
                        } else {
                            resSuccess(null, res);
                        }
                    });
                } else {
                    resError(106, null, res);
                }
            } else {
                resError(105, null, res);
            }

            break;

        default:
            // Unknown command
            resError(100, null, res);
    }

    return next();

});

/**
 * DELETE
 */
server.del(pathRegEx, function (req, res, next) {

    // Check request
    checkReq(config, req, res);

    // Set path
    var path = config.base + "/" + req.params[1];

    // Make sure it exists
    if (fs.existsSync(path)) {
        // Remove file or directory
        fs.remove(path, function (err) {
            if (err) {
                resError(108, err, res);
            } else {
                resSuccess(null, res);
            }
        });
    } else {
        resError(103, null, res);
    }

    return next();

});

/**
 * START SERVER
 */
server.listen(config.port, function () {
    console.log("%s listening at %s", server.name, server.url);
});
<|endoftext|>


<commit_before>/*!
 * regex-cache <https://github.com/jonschlinkert/regex-cache>
 *
 * Copyright (c) 2015 Jon Schlinkert.
 * Licensed under the MIT license.
 */

'use strict';

var isPrimitive = require('is-primitive');
var equal = require('is-equal-shallow');
var basic = {};
var cache = {};

/**
 * Expose `regexCache`
 */

module.exports = regexCache;

/**
 * Memoize the results of a call to the new RegExp constructor.
 *
 * @param  {Function} fn [description]
 * @param  {String} str [description]
 * @param  {Options} options [description]
 * @param  {Boolean} nocompare [description]
 * @return {RegExp}
 */

function regexCache(fn, str, opts) {
  var key = '_default_', regex, cached;

  if (!str && !opts) {
    if (typeof fn !== 'function') {
      return fn;
    }
    return basic[key] || (basic[key] = fn(str));
  }

  var isString = typeof str === 'string';
  if (isString) {
    if (!opts) {
      return basic[str] || (basic[str] = fn(str));
    }
    key = str;
  } else {
    opts = str;
  }

  cached = cache[key];
  if (cached && equal(cached.opts, opts)) {
    return cached.regex;
  }

  memo(key, opts, (regex = fn(str, opts)));
  return regex;
}

function memo(key, opts, regex) {
  cache[key] = {regex: regex, opts: opts};
}

/**
 * Expose `cache`
 */

module.exports.cache = cache;
module.exports.basic = basic;
<commit_msg>Removed unused require<commit_after>/*!
 * regex-cache <https://github.com/jonschlinkert/regex-cache>
 *
 * Copyright (c) 2015 Jon Schlinkert.
 * Licensed under the MIT license.
 */

'use strict';

var equal = require('is-equal-shallow');
var basic = {};
var cache = {};

/**
 * Expose `regexCache`
 */

module.exports = regexCache;

/**
 * Memoize the results of a call to the new RegExp constructor.
 *
 * @param  {Function} fn [description]
 * @param  {String} str [description]
 * @param  {Options} options [description]
 * @param  {Boolean} nocompare [description]
 * @return {RegExp}
 */

function regexCache(fn, str, opts) {
  var key = '_default_', regex, cached;

  if (!str && !opts) {
    if (typeof fn !== 'function') {
      return fn;
    }
    return basic[key] || (basic[key] = fn(str));
  }

  var isString = typeof str === 'string';
  if (isString) {
    if (!opts) {
      return basic[str] || (basic[str] = fn(str));
    }
    key = str;
  } else {
    opts = str;
  }

  cached = cache[key];
  if (cached && equal(cached.opts, opts)) {
    return cached.regex;
  }

  memo(key, opts, (regex = fn(str, opts)));
  return regex;
}

function memo(key, opts, regex) {
  cache[key] = {regex: regex, opts: opts};
}

/**
 * Expose `cache`
 */

module.exports.cache = cache;
module.exports.basic = basic;
<|endoftext|>


<commit_before>const express = require('express');
const handlebars  = require('express-handlebars');
const app = express();

app.set('port', (process.env.PORT || 5000));

app.use(express.static(__dirname));

app.engine('.hbs', handlebars({
    defaultLayout : 'main',
    extname : '.hbs',
    layoutsDir : 'views/layouts/',
    partialsDir : 'views/partials/',
}));
app.set('view engine', '.hbs');

// HTTPS Enforcement Redirect
app.get('*',function(req, res, next){

    const exceptions = req.hostname === 'localhost' ||
                       req.hostname.match(/\.local$/);

    if (!req.secure && !exceptions) {
        console.log(`Insecure: ${req.hostname}`);
        res.redirect(301, `https://derek.business${req.originalUrl}`);
    } else {
        next();
    }

});

// Canonical Hostname Enforcement Redirect
app.get('*',function(req, res, next){

    const exceptions = req.hostname === 'localhost' ||
                       req.hostname.match(/\.local$/) ||
                       req.hostname.match(/\.herokuapp.com$/) ||
                       req.hostname.match(/^derek\.business$/);

    if (!exceptions) {
        console.log(`Incorrect hostname: ${req.hostname}`);
        res.redirect(301, `https://derek.business${req.originalUrl}`);
    } else {
        next();
    }

});

app.get('/', function(req, res) {
  res.render('home');
});

app.listen(app.get('port'), () => {
  console.log('Node app is running on port', app.get('port'));
});
<commit_msg>MORE logs<commit_after>const express = require('express');
const handlebars  = require('express-handlebars');
const app = express();

app.set('port', (process.env.PORT || 5000));

app.use(express.static(__dirname));

app.engine('.hbs', handlebars({
    defaultLayout : 'main',
    extname : '.hbs',
    layoutsDir : 'views/layouts/',
    partialsDir : 'views/partials/',
}));
app.set('view engine', '.hbs');

// HTTPS Enforcement Redirect
app.get('*',function(req, res, next){

    const exceptions = req.hostname === 'localhost' ||
                       req.hostname.match(/\.local$/);

    if (!req.secure && !exceptions) {
        console.log(`Insecure: ${req.hostname}`);
        console.log(`Insecure: ${req.protocol}`);
        console.log(`Insecure: ${req.secure}`);
        res.redirect(301, `https://derek.business${req.originalUrl}`);
    } else {
        next();
    }

});

// Canonical Hostname Enforcement Redirect
app.get('*',function(req, res, next){

    const exceptions = req.hostname === 'localhost' ||
                       req.hostname.match(/\.local$/) ||
                       req.hostname.match(/\.herokuapp.com$/) ||
                       req.hostname.match(/^derek\.business$/);

    if (!exceptions) {
        console.log(`Incorrect hostname: ${req.hostname}`);
        res.redirect(301, `https://derek.business${req.originalUrl}`);
    } else {
        next();
    }

});

app.get('/', function(req, res) {
  res.render('home');
});

app.listen(app.get('port'), () => {
  console.log('Node app is running on port', app.get('port'));
});
<|endoftext|>


<commit_before><commit_msg>build doc bundle<commit_after><|endoftext|>


<commit_before>/* ========================================================================
 * Bootstrap: tooltip.js v3.3.1
 * http://getbootstrap.com/javascript/#tooltip
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */

+function ($) {
  'use strict';

  // TOOLTIP PUBLIC CLASS DEFINITION
  // ===============================

  var Tooltip = function (element, options) {
    this.type       =
    this.options    =
    this.enabled    =
    this.timeout    =
    this.hoverState =
    this.$element   = null

    this.init('tooltip', element, options)
  }

  Tooltip.VERSION  = '3.3.1'

  Tooltip.TRANSITION_DURATION = 150

  Tooltip.DEFAULTS = {
    animation: true,
    placement: 'top',
    selector: false,
    template: '

',
    trigger: 'hover focus',
    title: '',
    delay: 0,
    html: false,
    container: false,
    viewport: {
      selector: 'body',
      padding: 0
    }
  }

  Tooltip.prototype.init = function (type, element, options) {
    this.enabled   = true
    this.type      = type
    this.$element  = $(element)
    this.options   = this.getOptions(options)
    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)

    if (this.$element[0] instanceof window.Document && !this.options.selector) {
      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!');
    }

    var triggers = this.options.trigger.split(' ')

    for (var i = triggers.length; i--;) {
      var trigger = triggers[i]

      if (trigger == 'click') {
        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
      } else if (trigger != 'manual') {
        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'

        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
      }
    }

    this.options.selector ?
      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
      this.fixTitle()
  }

  Tooltip.prototype.getDefaults = function () {
    return Tooltip.DEFAULTS
  }

  Tooltip.prototype.getOptions = function (options) {
    options = $.extend({}, this.getDefaults(), this.$element.data(), options)

    if (options.delay && typeof options.delay == 'number') {
      options.delay = {
        show: options.delay,
        hide: options.delay
      }
    }

    return options
  }

  Tooltip.prototype.getDelegateOptions = function () {
    var options  = {}
    var defaults = this.getDefaults()

    this._options && $.each(this._options, function (key, value) {
      if (defaults[key] != value) options[key] = value
    })

    return options
  }

  Tooltip.prototype.enter = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)

    if (self && self.$tip && self.$tip.is(':visible')) {
      self.hoverState = 'in'
      return
    }

    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
    }

    clearTimeout(self.timeout)

    self.hoverState = 'in'

    if (!self.options.delay || !self.options.delay.show) return self.show()

    self.timeout = setTimeout(function () {
      if (self.hoverState == 'in') self.show()
    }, self.options.delay.show)
  }

  Tooltip.prototype.leave = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)

    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
    }

    clearTimeout(self.timeout)

    self.hoverState = 'out'

    if (!self.options.delay || !self.options.delay.hide) return self.hide()

    self.timeout = setTimeout(function () {
      if (self.hoverState == 'out') self.hide()
    }, self.options.delay.hide)
  }

  Tooltip.prototype.show = function () {
    var e = $.Event('show.bs.' + this.type)

    if (this.hasContent() && this.enabled) {
      this.$element.trigger(e)

      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
      if (e.isDefaultPrevented() || !inDom) return
      var that = this

      var $tip = this.tip()

      var tipId = this.getUID(this.type)

      this.setContent()
      $tip.attr('id', tipId)
      this.$element.attr('aria-describedby', tipId)

      if (this.options.animation) $tip.addClass('fade')

      var placement = typeof this.options.placement == 'function' ?
        this.options.placement.call(this, $tip[0], this.$element[0]) :
        this.options.placement

      var autoToken = /\s?auto?\s?/i
      var autoPlace = autoToken.test(placement)
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'

      $tip
        .detach()
        .css({ top: 0, left: 0, display: 'block' })
        .addClass(placement)
        .data('bs.' + this.type, this)

      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)

      var pos          = this.getPosition()
      var actualWidth  = $tip[0].offsetWidth
      var actualHeight = $tip[0].offsetHeight

      if (autoPlace) {
        var orgPlacement = placement
        var $container   = this.options.container ? $(this.options.container) : this.$element.parent()
        var containerDim = this.getPosition($container)

        placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top'    :
                    placement == 'top'    && pos.top    - actualHeight < containerDim.top    ? 'bottom' :
                    placement == 'right'  && pos.right  + actualWidth  > containerDim.width  ? 'left'   :
                    placement == 'left'   && pos.left   - actualWidth  < containerDim.left   ? 'right'  :
                    placement

        $tip
          .removeClass(orgPlacement)
          .addClass(placement)
      }

      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)

      this.applyPlacement(calculatedOffset, placement)

      var complete = function () {
        var prevHoverState = that.hoverState
        that.$element.trigger('shown.bs.' + that.type)
        that.hoverState = null

        if (prevHoverState == 'out') that.leave(that)
      }

      $.support.transition && this.$tip.hasClass('fade') ?
        $tip
          .one('bsTransitionEnd', complete)
          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
        complete()
    }
  }

  Tooltip.prototype.applyPlacement = function (offset, placement) {
    var $tip   = this.tip()
    var width  = $tip[0].offsetWidth
    var height = $tip[0].offsetHeight

    // manually read margins because getBoundingClientRect includes difference
    var marginTop = parseInt($tip.css('margin-top'), 10)
    var marginLeft = parseInt($tip.css('margin-left'), 10)

    // we must check for NaN for ie 8/9
    if (isNaN(marginTop))  marginTop  = 0
    if (isNaN(marginLeft)) marginLeft = 0

    offset.top  = offset.top  + marginTop
    offset.left = offset.left + marginLeft

    // $.fn.offset doesn't round pixel values
    // so we use setOffset directly with our own function B-0
    $.offset.setOffset($tip[0], $.extend({
      using: function (props) {
        $tip.css({
          top: Math.round(props.top),
          left: Math.round(props.left)
        })
      }
    }, offset), 0)

    $tip.addClass('in')

    // check to see if placing tip in new offset caused the tip to resize itself
    var actualWidth  = $tip[0].offsetWidth
    var actualHeight = $tip[0].offsetHeight

    if (placement == 'top' && actualHeight != height) {
      offset.top = offset.top + height - actualHeight
    }

    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)

    if (delta.left) offset.left += delta.left
    else offset.top += delta.top

    var isVertical          = /top|bottom/.test(placement)
    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'

    $tip.offset(offset)
    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
  }

  Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
    this.arrow()
      .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
      .css(isHorizontal ? 'top' : 'left', '')
  }

  Tooltip.prototype.setContent = function () {
    var $tip  = this.tip()
    var title = this.getTitle()

    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
    $tip.removeClass('fade in top bottom left right')
  }

  Tooltip.prototype.hide = function (callback) {
    var that = this
    var $tip = this.tip()
    var e    = $.Event('hide.bs.' + this.type)

    function complete() {
      if (that.hoverState != 'in') $tip.detach()
      that.$element
        .removeAttr('aria-describedby')
        .trigger('hidden.bs.' + that.type)
      callback && callback()
    }

    this.$element.trigger(e)

    if (e.isDefaultPrevented()) return

    $tip.removeClass('in')

    $.support.transition && this.$tip.hasClass('fade') ?
      $tip
        .one('bsTransitionEnd', complete)
        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
      complete()

    this.hoverState = null

    return this
  }

  Tooltip.prototype.fixTitle = function () {
    var $e = this.$element
    if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
    }
  }

  Tooltip.prototype.hasContent = function () {
    return this.getTitle()
  }

  Tooltip.prototype.getPosition = function ($element) {
    $element   = $element || this.$element

    var el     = $element[0]
    var isBody = el.tagName == 'BODY'

    var elRect    = el.getBoundingClientRect()
    if (elRect.width == null) {
      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
    }
    var elOffset  = isBody ? { top: 0, left: 0 } : $element.offset()
    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null

    return $.extend({}, elRect, scroll, outerDims, elOffset)
  }

  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }

  }

  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
    var delta = { top: 0, left: 0 }
    if (!this.$viewport) return delta

    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
    var viewportDimensions = this.getPosition(this.$viewport)

    if (/right|left/.test(placement)) {
      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
      if (topEdgeOffset < viewportDimensions.top) { // top overflow
        delta.top = viewportDimensions.top - topEdgeOffset
      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
      }
    } else {
      var leftEdgeOffset  = pos.left - viewportPadding
      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
        delta.left = viewportDimensions.left - leftEdgeOffset
      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
      }
    }

    return delta
  }

  Tooltip.prototype.getTitle = function () {
    var title
    var $e = this.$element
    var o  = this.options

    title = $e.attr('data-original-title')
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

    return title
  }

  Tooltip.prototype.getUID = function (prefix) {
    do prefix += ~~(Math.random() * 1000000)
    while (document.getElementById(prefix))
    return prefix
  }

  Tooltip.prototype.tip = function () {
    return (this.$tip = this.$tip || $(this.options.template))
  }

  Tooltip.prototype.arrow = function () {
    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
  }

  Tooltip.prototype.enable = function () {
    this.enabled = true
  }

  Tooltip.prototype.disable = function () {
    this.enabled = false
  }

  Tooltip.prototype.toggleEnabled = function () {
    this.enabled = !this.enabled
  }

  Tooltip.prototype.toggle = function (e) {
    var self = this
    if (e) {
      self = $(e.currentTarget).data('bs.' + this.type)
      if (!self) {
        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
        $(e.currentTarget).data('bs.' + this.type, self)
      }
    }

    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  }

  Tooltip.prototype.destroy = function () {
    var that = this
    clearTimeout(this.timeout)
    this.hide(function () {
      that.$element.off('.' + that.type).removeData('bs.' + that.type)
    })
  }

  // TOOLTIP PLUGIN DEFINITION
  // =========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.tooltip')
      var options = typeof option == 'object' && option

      if (!data && option == 'destroy') return
      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.tooltip

  $.fn.tooltip             = Plugin
  $.fn.tooltip.Constructor = Tooltip

  // TOOLTIP NO CONFLICT
  // ===================

  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
    return this
  }

}(jQuery);
<commit_msg>window.Document doesn't exist in IE8<commit_after>/* ========================================================================
 * Bootstrap: tooltip.js v3.3.1
 * http://getbootstrap.com/javascript/#tooltip
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */

+function ($) {
  'use strict';

  // TOOLTIP PUBLIC CLASS DEFINITION
  // ===============================

  var Tooltip = function (element, options) {
    this.type       =
    this.options    =
    this.enabled    =
    this.timeout    =
    this.hoverState =
    this.$element   = null

    this.init('tooltip', element, options)
  }

  Tooltip.VERSION  = '3.3.1'

  Tooltip.TRANSITION_DURATION = 150

  Tooltip.DEFAULTS = {
    animation: true,
    placement: 'top',
    selector: false,
    template: '

',
    trigger: 'hover focus',
    title: '',
    delay: 0,
    html: false,
    container: false,
    viewport: {
      selector: 'body',
      padding: 0
    }
  }

  Tooltip.prototype.init = function (type, element, options) {
    this.enabled   = true
    this.type      = type
    this.$element  = $(element)
    this.options   = this.getOptions(options)
    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)

    if (this.$element[0] instanceof document.constructor && !this.options.selector) {
      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!');
    }

    var triggers = this.options.trigger.split(' ')

    for (var i = triggers.length; i--;) {
      var trigger = triggers[i]

      if (trigger == 'click') {
        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
      } else if (trigger != 'manual') {
        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'

        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
      }
    }

    this.options.selector ?
      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
      this.fixTitle()
  }

  Tooltip.prototype.getDefaults = function () {
    return Tooltip.DEFAULTS
  }

  Tooltip.prototype.getOptions = function (options) {
    options = $.extend({}, this.getDefaults(), this.$element.data(), options)

    if (options.delay && typeof options.delay == 'number') {
      options.delay = {
        show: options.delay,
        hide: options.delay
      }
    }

    return options
  }

  Tooltip.prototype.getDelegateOptions = function () {
    var options  = {}
    var defaults = this.getDefaults()

    this._options && $.each(this._options, function (key, value) {
      if (defaults[key] != value) options[key] = value
    })

    return options
  }

  Tooltip.prototype.enter = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)

    if (self && self.$tip && self.$tip.is(':visible')) {
      self.hoverState = 'in'
      return
    }

    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
    }

    clearTimeout(self.timeout)

    self.hoverState = 'in'

    if (!self.options.delay || !self.options.delay.show) return self.show()

    self.timeout = setTimeout(function () {
      if (self.hoverState == 'in') self.show()
    }, self.options.delay.show)
  }

  Tooltip.prototype.leave = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)

    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
    }

    clearTimeout(self.timeout)

    self.hoverState = 'out'

    if (!self.options.delay || !self.options.delay.hide) return self.hide()

    self.timeout = setTimeout(function () {
      if (self.hoverState == 'out') self.hide()
    }, self.options.delay.hide)
  }

  Tooltip.prototype.show = function () {
    var e = $.Event('show.bs.' + this.type)

    if (this.hasContent() && this.enabled) {
      this.$element.trigger(e)

      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
      if (e.isDefaultPrevented() || !inDom) return
      var that = this

      var $tip = this.tip()

      var tipId = this.getUID(this.type)

      this.setContent()
      $tip.attr('id', tipId)
      this.$element.attr('aria-describedby', tipId)

      if (this.options.animation) $tip.addClass('fade')

      var placement = typeof this.options.placement == 'function' ?
        this.options.placement.call(this, $tip[0], this.$element[0]) :
        this.options.placement

      var autoToken = /\s?auto?\s?/i
      var autoPlace = autoToken.test(placement)
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'

      $tip
        .detach()
        .css({ top: 0, left: 0, display: 'block' })
        .addClass(placement)
        .data('bs.' + this.type, this)

      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)

      var pos          = this.getPosition()
      var actualWidth  = $tip[0].offsetWidth
      var actualHeight = $tip[0].offsetHeight

      if (autoPlace) {
        var orgPlacement = placement
        var $container   = this.options.container ? $(this.options.container) : this.$element.parent()
        var containerDim = this.getPosition($container)

        placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top'    :
                    placement == 'top'    && pos.top    - actualHeight < containerDim.top    ? 'bottom' :
                    placement == 'right'  && pos.right  + actualWidth  > containerDim.width  ? 'left'   :
                    placement == 'left'   && pos.left   - actualWidth  < containerDim.left   ? 'right'  :
                    placement

        $tip
          .removeClass(orgPlacement)
          .addClass(placement)
      }

      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)

      this.applyPlacement(calculatedOffset, placement)

      var complete = function () {
        var prevHoverState = that.hoverState
        that.$element.trigger('shown.bs.' + that.type)
        that.hoverState = null

        if (prevHoverState == 'out') that.leave(that)
      }

      $.support.transition && this.$tip.hasClass('fade') ?
        $tip
          .one('bsTransitionEnd', complete)
          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
        complete()
    }
  }

  Tooltip.prototype.applyPlacement = function (offset, placement) {
    var $tip   = this.tip()
    var width  = $tip[0].offsetWidth
    var height = $tip[0].offsetHeight

    // manually read margins because getBoundingClientRect includes difference
    var marginTop = parseInt($tip.css('margin-top'), 10)
    var marginLeft = parseInt($tip.css('margin-left'), 10)

    // we must check for NaN for ie 8/9
    if (isNaN(marginTop))  marginTop  = 0
    if (isNaN(marginLeft)) marginLeft = 0

    offset.top  = offset.top  + marginTop
    offset.left = offset.left + marginLeft

    // $.fn.offset doesn't round pixel values
    // so we use setOffset directly with our own function B-0
    $.offset.setOffset($tip[0], $.extend({
      using: function (props) {
        $tip.css({
          top: Math.round(props.top),
          left: Math.round(props.left)
        })
      }
    }, offset), 0)

    $tip.addClass('in')

    // check to see if placing tip in new offset caused the tip to resize itself
    var actualWidth  = $tip[0].offsetWidth
    var actualHeight = $tip[0].offsetHeight

    if (placement == 'top' && actualHeight != height) {
      offset.top = offset.top + height - actualHeight
    }

    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)

    if (delta.left) offset.left += delta.left
    else offset.top += delta.top

    var isVertical          = /top|bottom/.test(placement)
    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'

    $tip.offset(offset)
    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
  }

  Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
    this.arrow()
      .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
      .css(isHorizontal ? 'top' : 'left', '')
  }

  Tooltip.prototype.setContent = function () {
    var $tip  = this.tip()
    var title = this.getTitle()

    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
    $tip.removeClass('fade in top bottom left right')
  }

  Tooltip.prototype.hide = function (callback) {
    var that = this
    var $tip = this.tip()
    var e    = $.Event('hide.bs.' + this.type)

    function complete() {
      if (that.hoverState != 'in') $tip.detach()
      that.$element
        .removeAttr('aria-describedby')
        .trigger('hidden.bs.' + that.type)
      callback && callback()
    }

    this.$element.trigger(e)

    if (e.isDefaultPrevented()) return

    $tip.removeClass('in')

    $.support.transition && this.$tip.hasClass('fade') ?
      $tip
        .one('bsTransitionEnd', complete)
        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
      complete()

    this.hoverState = null

    return this
  }

  Tooltip.prototype.fixTitle = function () {
    var $e = this.$element
    if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
    }
  }

  Tooltip.prototype.hasContent = function () {
    return this.getTitle()
  }

  Tooltip.prototype.getPosition = function ($element) {
    $element   = $element || this.$element

    var el     = $element[0]
    var isBody = el.tagName == 'BODY'

    var elRect    = el.getBoundingClientRect()
    if (elRect.width == null) {
      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
    }
    var elOffset  = isBody ? { top: 0, left: 0 } : $element.offset()
    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null

    return $.extend({}, elRect, scroll, outerDims, elOffset)
  }

  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }

  }

  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
    var delta = { top: 0, left: 0 }
    if (!this.$viewport) return delta

    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
    var viewportDimensions = this.getPosition(this.$viewport)

    if (/right|left/.test(placement)) {
      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
      if (topEdgeOffset < viewportDimensions.top) { // top overflow
        delta.top = viewportDimensions.top - topEdgeOffset
      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
      }
    } else {
      var leftEdgeOffset  = pos.left - viewportPadding
      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
        delta.left = viewportDimensions.left - leftEdgeOffset
      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
      }
    }

    return delta
  }

  Tooltip.prototype.getTitle = function () {
    var title
    var $e = this.$element
    var o  = this.options

    title = $e.attr('data-original-title')
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

    return title
  }

  Tooltip.prototype.getUID = function (prefix) {
    do prefix += ~~(Math.random() * 1000000)
    while (document.getElementById(prefix))
    return prefix
  }

  Tooltip.prototype.tip = function () {
    return (this.$tip = this.$tip || $(this.options.template))
  }

  Tooltip.prototype.arrow = function () {
    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
  }

  Tooltip.prototype.enable = function () {
    this.enabled = true
  }

  Tooltip.prototype.disable = function () {
    this.enabled = false
  }

  Tooltip.prototype.toggleEnabled = function () {
    this.enabled = !this.enabled
  }

  Tooltip.prototype.toggle = function (e) {
    var self = this
    if (e) {
      self = $(e.currentTarget).data('bs.' + this.type)
      if (!self) {
        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
        $(e.currentTarget).data('bs.' + this.type, self)
      }
    }

    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  }

  Tooltip.prototype.destroy = function () {
    var that = this
    clearTimeout(this.timeout)
    this.hide(function () {
      that.$element.off('.' + that.type).removeData('bs.' + that.type)
    })
  }

  // TOOLTIP PLUGIN DEFINITION
  // =========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.tooltip')
      var options = typeof option == 'object' && option

      if (!data && option == 'destroy') return
      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.tooltip

  $.fn.tooltip             = Plugin
  $.fn.tooltip.Constructor = Tooltip

  // TOOLTIP NO CONFLICT
  // ===================

  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
    return this
  }

}(jQuery);
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  env: {
    node: true,
    mocha: true,
  },
  extends: 'eslint:recommended',
  rules: {
    // Possible Errors
    'no-cond-assign': 'error',
    'no-console': 'error',
    'no-constant-condition': 'error',
    'no-control-regex': 'error',
    'no-debugger': 'error',
    'no-dupe-args': 'error',
    'no-dupe-keys': 'error',
    'no-duplicate-case': 'error',
    'no-empty': 'error',
    'no-empty-character-class': 'error',
    'no-ex-assign': 'error',
    'no-extra-boolean-cast': 'error',
    'no-extra-parens': 'off',
    'no-extra-semi': 'error',
    'no-func-assign': 'error',
    'no-inner-declarations': ['error', 'functions'],
    'no-invalid-regexp': 'error',
    'no-irregular-whitespace': 'error',
    'no-negated-in-lhs': 'error',
    'no-obj-calls': 'error',
    'no-prototype-builtins': 'off',
    'no-regex-spaces': 'error',
    'no-sparse-arrays': 'error',
    'no-unexpected-multiline': 'error',
    'no-unreachable': 'error',
    'no-unsafe-finally': 'error',
    'use-isnan': 'error',
    'valid-jsdoc': 'warn', // this rule needs to be spec'd out more
    'valid-typeof': 'error',

    // Best Practices
    'accessor-pairs': 'error',
    'array-callback-return': 'warn',
    'block-scoped-var': 'off',
    'complexity': 'error',
    'consistent-return': 'off',
    'curly': 'error',
    'default-case': 'error',
    'dot-location': [
      'error',
      'property'
    ],
    'dot-notation': 'error',
    'eqeqeq': 'error',
    'guard-for-in': 'warn',
    'no-alert': 'error',
    'no-caller': 'error',
    'no-case-declarations': 'off',  // ES6 rule
    'no-div-regex': 'error',
    'no-else-return': 'off',
    'no-empty-function': 'error',
    'no-empty-pattern': 'error',
    'no-eq-null': 'error',
    'no-eval': 'error',
    'no-extend-native': 'error',
    'no-extra-bind': 'error',
    'no-extra-label': 'error',
    'no-fallthrough': 'error',
    'no-floating-decimal': 'error',
    'no-implicit-coercion': 'error',
    'no-implicit-globals': 'error',
    'no-implied-eval': 'error',
    'no-invalid-this': 'off', // TODO check this rule later
    'no-iterator': 'error',
    'no-labels': 'error',
    'no-lone-blocks': 'error',
    'no-loop-func': 'error',
    'no-magic-numbers': 'off',
    'no-multi-spaces': 'error',
    'no-multi-str': 'error',
    'no-native-reassign': 'error',
    'no-new': 'error',
    'no-new-func': 'error',
    'no-new-wrappers': 'error',
    'no-octal': 'error',
    'no-octal-escape': 'error',
    'no-param-reassign': 'off',
    'no-proto': 'error',
    'no-redeclare': [
      'error',
      { 'builtinGlobals': true }
    ],
    'no-return-assign': 'error',
    'no-script-url': 'error',
    'no-self-assign': 'error',
    'no-self-compare': 'error',
    'no-sequences': 'error',

    // still need to double check the rest
    'comma-dangle': [
      'error',
      'only-multiline',
    ],
    'array-bracket-spacing': 'off',
    'arrow-body-style': 'error',
    'arrow-parens': 'error',
    'arrow-spacing': 'error',
    'block-spacing': 'off',
    'brace-style': [
      'error',
      '1tbs',
      {
        'allowSingleLine': true
      }
    ],
    'callback-return': 'error',
    'camelcase': 'off',
    'comma-spacing': 'off',
    'comma-style': [
      'error',
      'last'
    ],
    'computed-property-spacing': [
      'error',
      'never'
    ],
    'consistent-this': 'off',
    'eol-last': 'off',
    'func-names': 'off',
    'func-style': 'off',
    'generator-star-spacing': 'error',
    'global-require': 'off',
    'handle-callback-err': 'off',
    'id-blacklist': 'error',
    'id-length': 'off',
    'id-match': 'error',
    'indent': 'off',
    'init-declarations': 'off',
    'jsx-quotes': 'error',
    'key-spacing': 'off',
    'keyword-spacing': 'off',
    'linebreak-style': [
      'error',
      'unix'
    ],
    'lines-around-comment': 'off',
    'max-depth': 'off',
    'max-len': 'off',
    'max-lines': 'off',
    'max-nested-callbacks': 'error',
    'max-params': 'off',
    'max-statements': 'off',
    'max-statements-per-line': 'off',
    'new-parens': 'off',
    'newline-after-var': 'off',
    'newline-before-return': 'off',
    'newline-per-chained-call': 'off',
    'no-array-constructor': 'error',
    'no-bitwise': 'off',
    'no-catch-shadow': 'error',
    'no-confusing-arrow': 'error',
    'no-continue': 'error',
    'no-duplicate-imports': 'error',
    'no-inline-comments': 'off',
    'no-label-var': 'error',
    'no-lonely-if': 'off',
    'no-mixed-operators': 'off',
    'no-mixed-requires': 'error',
    'no-multiple-empty-lines': 'error',
    'no-negated-condition': 'off',
    'no-nested-ternary': 'off',
    'no-new-object': 'error',
    'no-new-require': 'error',
    'no-path-concat': 'off',
    'no-plusplus': 'off',
    'no-process-env': 'off',
    'no-process-exit': 'off',
    'no-restricted-globals': 'error',
    'no-restricted-imports': 'error',
    'no-restricted-modules': 'error',
    'no-restricted-syntax': 'error',
    'no-shadow': 'off',
    'no-shadow-restricted-names': 'error',
    'no-spaced-func': 'error',
    'no-sync': 'off',
    'no-ternary': 'off',
    'no-throw-literal': 'off',
    'no-trailing-spaces': [
      'error',
      {
        'skipBlankLines': true
      }
    ],
    'no-undef-init': 'off',
    'no-undefined': 'off',
    'no-underscore-dangle': 'off',
    'no-unmodified-loop-condition': 'error',
    'no-unneeded-ternary': 'error',
    'no-unused-expressions': 'error',
    'no-use-before-define': 'off',
    'no-useless-call': 'error',
    'no-useless-computed-key': 'error',
    'no-useless-concat': 'error',
    'no-useless-constructor': 'error',
    'no-useless-escape': 'off',
    'no-useless-rename': 'error',
    'no-var': 'off',
    'no-void': 'off',
    'no-warning-comments': 'off',
    'no-whitespace-before-property': 'error',
    'no-with': 'error',
    'object-curly-newline': 'off',
    'object-curly-spacing': 'off',
    'object-property-newline': [
      'error',
      {
        'allowMultiplePropertiesPerLine': true
      }
    ],
    'object-shorthand': 'off',
    'one-var': 'off',
    'one-var-declaration-per-line': 'off',
    'operator-assignment': 'off',
    'operator-linebreak': 'error',
    'padded-blocks': 'off',
    'prefer-arrow-callback': 'off',
    'prefer-const': 'error',
    'prefer-reflect': 'off',
    'prefer-rest-params': 'error',
    'prefer-spread': 'off',
    'prefer-template': 'off',
    'quote-props': 'off',
    'quotes': 'off',
    'radix': 'off',
    'require-jsdoc': 'off',
    'require-yield': 'error',
    'rest-spread-spacing': 'error',
    'semi': 'off',
    'semi-spacing': 'off',
    'sort-imports': 'error',
    'sort-vars': 'off',
    'space-before-blocks': 'off',
    'space-before-function-paren': 'off',
    'space-in-parens': [
      'error',
      'never'
    ],
    'space-infix-ops': 'off',
    'space-unary-ops': 'error',
    'spaced-comment': [
      'error',
      'always'
    ],
    'strict': 'off',
    'template-curly-spacing': 'error',
    'unicode-bom': [
      'error',
      'never'
    ],
    'vars-on-top': 'off',
    'wrap-regex': 'off',
    'yield-star-spacing': 'error',
    'yoda': 'off'
  }
};
<commit_msg>finish checking variables + best practices sections<commit_after>'use strict';

module.exports = {
  env: {
    node: true,
    mocha: true,
  },
  extends: 'eslint:recommended',
  rules: {
    // Possible Errors
    'no-cond-assign': 'error',
    'no-console': 'error',
    'no-constant-condition': 'error',
    'no-control-regex': 'error',
    'no-debugger': 'error',
    'no-dupe-args': 'error',
    'no-dupe-keys': 'error',
    'no-duplicate-case': 'error',
    'no-empty': 'error',
    'no-empty-character-class': 'error',
    'no-ex-assign': 'error',
    'no-extra-boolean-cast': 'error',
    'no-extra-parens': 'off',
    'no-extra-semi': 'error',
    'no-func-assign': 'error',
    'no-inner-declarations': ['error', 'functions'],
    'no-invalid-regexp': 'error',
    'no-irregular-whitespace': 'error',
    'no-negated-in-lhs': 'error',
    'no-obj-calls': 'error',
    'no-prototype-builtins': 'off',
    'no-regex-spaces': 'error',
    'no-sparse-arrays': 'error',
    'no-unexpected-multiline': 'error',
    'no-unreachable': 'error',
    'no-unsafe-finally': 'error',
    'use-isnan': 'error',
    'valid-jsdoc': 'warn', // this rule needs to be spec'd out more
    'valid-typeof': 'error',

    // Best Practices
    'accessor-pairs': 'error',
    'array-callback-return': 'warn',
    'block-scoped-var': 'off',
    'complexity': 'error',
    'consistent-return': 'off',
    'curly': 'error',
    'default-case': 'error',
    'dot-location': [
      'error',
      'property'
    ],
    'dot-notation': 'error',
    'eqeqeq': 'error',
    'guard-for-in': 'warn',
    'no-alert': 'error',
    'no-caller': 'error',
    'no-case-declarations': 'off',  // ES6 rule
    'no-div-regex': 'error',
    'no-else-return': 'off',
    'no-empty-function': 'error',
    'no-empty-pattern': 'error',
    'no-eq-null': 'error',
    'no-eval': 'error',
    'no-extend-native': 'error',
    'no-extra-bind': 'error',
    'no-extra-label': 'error',
    'no-fallthrough': 'error',
    'no-floating-decimal': 'error',
    'no-implicit-coercion': 'error',
    'no-implicit-globals': 'error',
    'no-implied-eval': 'error',
    'no-invalid-this': 'off', // TODO check this rule later
    'no-iterator': 'error',
    'no-labels': 'error',
    'no-lone-blocks': 'error',
    'no-loop-func': 'error',
    'no-magic-numbers': 'off',
    'no-multi-spaces': 'error',
    'no-multi-str': 'error',
    'no-native-reassign': 'error',
    'no-new': 'error',
    'no-new-func': 'error',
    'no-new-wrappers': 'error',
    'no-octal': 'error',
    'no-octal-escape': 'error',
    'no-param-reassign': 'off',
    'no-proto': 'error',
    'no-redeclare': [
      'error',
      { 'builtinGlobals': true }
    ],
    'no-return-assign': 'error',
    'no-script-url': 'error',
    'no-self-assign': 'error',
    'no-self-compare': 'error',
    'no-sequences': 'error',
    'no-throw-literal': 'error',
    'no-unmodified-loop-condition': 'error',
    'no-unused-expressions': 'error',
    'no-unused-labels': 'error',
    'no-useless-call': 'error',
    'no-useless-concat': 'error',
    'no-useless-escape': 'error',
    'no-void': 'error',
    'no-warning-comments': 'off',
    'no-with': 'error',
    'radix': 'as-needed',
    'vars-on-top': 'off',
    'wrap-iife': 'outside',
    'yoda': ['error', 'never', { 'exceptRange': true }],
    'strict': 'global',

    // Variables
    'init-declarations': 'off',
    'no-catch-shadow': 'off', // < IE8 rule
    'no-delete-var': 'error',
    'no-label-var': 'error',
    'no-restricted-globals': 'error',
    'no-shadow': 'off',
    'no-shadow-restricted-names': 'error',
    'no-undef': 'error',
    'no-undef-init': 'error',
    'no-undefined': 'off',
    'no-unused-vars': ['error', { 'vars': 'all', 'args': 'after-used' }],
    'no-use-before-define': ['error', { 'functions': false, 'classes': true }],

    // still need to double check the rest
    'comma-dangle': [
      'error',
      'only-multiline',
    ],
    'array-bracket-spacing': 'off',
    'arrow-body-style': 'error',
    'arrow-parens': 'error',
    'arrow-spacing': 'error',
    'block-spacing': 'off',
    'brace-style': [
      'error',
      '1tbs',
      {
        'allowSingleLine': true
      }
    ],
    'callback-return': 'error',
    'camelcase': 'off',
    'comma-spacing': 'off',
    'comma-style': [
      'error',
      'last'
    ],
    'computed-property-spacing': [
      'error',
      'never'
    ],
    'consistent-this': 'off',
    'eol-last': 'off',
    'func-names': 'off',
    'func-style': 'off',
    'generator-star-spacing': 'error',
    'global-require': 'off',
    'handle-callback-err': 'off',
    'id-blacklist': 'error',
    'id-length': 'off',
    'id-match': 'error',
    'indent': 'off',
    'jsx-quotes': 'error',
    'key-spacing': 'off',
    'keyword-spacing': 'off',
    'linebreak-style': [
      'error',
      'unix'
    ],
    'lines-around-comment': 'off',
    'max-depth': 'off',
    'max-len': 'off',
    'max-lines': 'off',
    'max-nested-callbacks': 'error',
    'max-params': 'off',
    'max-statements': 'off',
    'max-statements-per-line': 'off',
    'new-parens': 'off',
    'newline-after-var': 'off',
    'newline-before-return': 'off',
    'newline-per-chained-call': 'off',
    'no-array-constructor': 'error',
    'no-bitwise': 'off',
    'no-confusing-arrow': 'error',
    'no-continue': 'error',
    'no-duplicate-imports': 'error',
    'no-inline-comments': 'off',
    'no-lonely-if': 'off',
    'no-mixed-operators': 'off',
    'no-mixed-requires': 'error',
    'no-multiple-empty-lines': 'error',
    'no-negated-condition': 'off',
    'no-nested-ternary': 'off',
    'no-new-object': 'error',
    'no-new-require': 'error',
    'no-path-concat': 'off',
    'no-plusplus': 'off',
    'no-process-env': 'off',
    'no-process-exit': 'off',
    'no-restricted-imports': 'error',
    'no-restricted-modules': 'error',
    'no-restricted-syntax': 'error',
    'no-spaced-func': 'error',
    'no-sync': 'off',
    'no-ternary': 'off',
    'no-trailing-spaces': [
      'error',
      {
        'skipBlankLines': true
      }
    ],
    'no-underscore-dangle': 'off',
    'no-unneeded-ternary': 'error',

    'no-useless-computed-key': 'error',
    'no-useless-constructor': 'error',
    'no-useless-rename': 'error',
    'no-var': 'off',
    'no-whitespace-before-property': 'error',
    'object-curly-newline': 'off',
    'object-curly-spacing': 'off',
    'object-property-newline': [
      'error',
      {
        'allowMultiplePropertiesPerLine': true
      }
    ],
    'object-shorthand': 'off',
    'one-var': 'off',
    'one-var-declaration-per-line': 'off',
    'operator-assignment': 'off',
    'operator-linebreak': 'error',
    'padded-blocks': 'off',
    'prefer-arrow-callback': 'off',
    'prefer-const': 'error',
    'prefer-reflect': 'off',
    'prefer-rest-params': 'error',
    'prefer-spread': 'off',
    'prefer-template': 'off',
    'quote-props': 'off',
    'quotes': 'off',
    'require-jsdoc': 'off',
    'require-yield': 'error',
    'rest-spread-spacing': 'error',
    'semi': 'off',
    'semi-spacing': 'off',
    'sort-imports': 'error',
    'sort-vars': 'off',
    'space-before-blocks': 'off',
    'space-before-function-paren': 'off',
    'space-in-parens': [
      'error',
      'never'
    ],
    'space-infix-ops': 'off',
    'space-unary-ops': 'error',
    'spaced-comment': [
      'error',
      'always'
    ],
    'template-curly-spacing': 'error',
    'unicode-bom': [
      'error',
      'never'
    ],
    'wrap-regex': 'off',
    'yield-star-spacing': 'error',
  }
};
<|endoftext|>


<commit_before>
/*!
 * nodejs-express-mongoose-demo
 * Copyright(c) 2013 Madhusudhan Srinivasa <madhums8@gmail.com>
 * MIT Licensed
 */
/**
 * Module dependencies
 */

var fs = require('fs');
var express = require('express');
var mongoose = require('mongoose');
var passport = require('passport');
var config = require('config');

var app = express();
var port = process.env.PORT || 3000;

// Connect to mongodb
var connect = function () {
  var options = { server: { socketOptions: { keepAlive: 1 } } };
  mongoose.connect(config.db, options);
};
connect();

mongoose.connection.on('error', console.log);
mongoose.connection.on('disconnected', connect);

// Bootstrap models
fs.readdirSync(__dirname + '/app/models').forEach(function (file) {
  if (~file.indexOf('.js')) require(__dirname + '/app/models/' + file);
});

// Bootstrap passport config
require('./config/passport')(passport, config);

// Bootstrap application settings
require('./config/express')(app, passport);

// Bootstrap routes
require('./config/routes')(app, passport);

app.listen(port, 'port number');
console.log('Express app started on port ' + port);

/**
 * Expose
 */

module.exports = app;
<commit_msg>config reset.<commit_after>
/*!
 * nodejs-express-mongoose-demo
 * Copyright(c) 2013 Madhusudhan Srinivasa <madhums8@gmail.com>
 * MIT Licensed
 */
/**
 * Module dependencies
 */

var fs = require('fs');
var express = require('express');
var mongoose = require('mongoose');
var passport = require('passport');
var config = require('./config/config');

var app = express();
var port = process.env.PORT || 3000;

// Connect to mongodb
var connect = function () {
  var options = { server: { socketOptions: { keepAlive: 1 } } };
  mongoose.connect(config.db, options);
};
connect();

mongoose.connection.on('error', console.log);
mongoose.connection.on('disconnected', connect);

// Bootstrap models
fs.readdirSync(__dirname + '/app/models').forEach(function (file) {
  if (~file.indexOf('.js')) require(__dirname + '/app/models/' + file);
});

// Bootstrap passport config
require('./config/passport')(passport, config);

// Bootstrap application settings
require('./config/express')(app, passport);

// Bootstrap routes
require('./config/routes')(app, passport);

console.log('Express app started on port ' + port);

/**
 * Expose
 */

module.exports = app;
<|endoftext|>


<commit_before>var Octokat = require('octokat')
var octo = new Octokat({
  token: process.env.GITHUB_OGN_TOKEN
})
var Promise = require('bluebird')
var isArray = require('isarray')

module.exports = function removeNotifications (user) {
  if (typeof user !== 'string') {
    if (!isArray(user)) {
      throw new TypeError('Expected a string or an array')
    }
  } else {
    user = [user]
  }

  return Promise.try(function () {
    return octo.notifications.fetch()
  }).each(function (repo) {
    var id = repo.id
    return Promise.try(function () {
      return octo.fromUrl(repo.subject.url).fetch()
    }).then(function (notification) {
      if (user.indexOf(notification.user.login) > -1) {
        return octo.notifications.threads(id).update()
      }
    }).then(function () {
      // Should only happen once
      return `Ignored ${user}`
    }).catch(function (err) {
      console.log(err)
    })
  }).catch(function (err) {
    console.log(err)
  })
}
<commit_msg>Changed env var<commit_after>var Octokat = require('octokat')
var octo = new Octokat({
  token: process.env.IGNOREGITHUBNOTIFICATIONS
})
var Promise = require('bluebird')
var isArray = require('isarray')

module.exports = function removeNotifications (user) {
  if (typeof user !== 'string') {
    if (!isArray(user)) {
      throw new TypeError('Expected a string or an array')
    }
  } else {
    user = [user]
  }

  return Promise.try(function () {
    return octo.notifications.fetch()
  }).each(function (repo) {
    var id = repo.id
    return Promise.try(function () {
      return octo.fromUrl(repo.subject.url).fetch()
    }).then(function (notification) {
      if (user.indexOf(notification.user.login) > -1) {
        return octo.notifications.threads(id).update()
      }
    }).then(function () {
      // Should only happen once
      return `Ignored ${user}`
    }).catch(function (err) {
      console.log(err)
    })
  }).catch(function (err) {
    console.log(err)
  })
}
<|endoftext|>


<commit_before>const compression = require('compression');
const bodyParser = require('body-parser');
const express = require('express');
const fs = require('fs');
const http = require('http');
const morgan = require('morgan');

const log = require('./log');
const applianceService = require('./service/applianceService');
const resourceService = require('./service/resourceService');

const PORT = 7010;

const app = express();
app.use(compression());
app.use(bodyParser.json());
app.use(morgan('combined', {
  stream: fs.createWriteStream(`${__dirname}/access.log`, {
    flags: 'a',
  }),
}));

let reqId = 0;
app.use((req, res, next) => {
  reqId += 1;
  req.log = log.child({ reqId });
  req.log.info({
    url: req.originalUrl,
    method: req.method,
    params: req.params,
    query: req.query,
  },
    'REST request received');
  next();
});

app.post('/rest/global/appliances', applianceService.post);
app.delete('/rest/global/appliances/:id', applianceService.delete);
app.get('/rest/global/appliances', applianceService.getList);
app.get('/rest/global/appliances/:id', applianceService.get);

app.get('/rest/global/:category', resourceService.getList);
app.get('/rest/global/:category/:id', resourceService.get);

const server = http.createServer(app);
server.listen(PORT);
<commit_msg>Fix code format<commit_after>const compression = require('compression');
const bodyParser = require('body-parser');
const express = require('express');
const fs = require('fs');
const http = require('http');
const morgan = require('morgan');

const log = require('./log');
const applianceService = require('./service/applianceService');
const resourceService = require('./service/resourceService');

const PORT = 7010;

const app = express();
app.use(compression());
app.use(bodyParser.json());
app.use(morgan('combined', {
  stream: fs.createWriteStream(`${__dirname}/access.log`, {
    flags: 'a',
  }),
}));

let reqId = 0;
app.use((req, res, next) => {
  reqId += 1;
  req.log = log.child({
    reqId
  });
  req.log.info({
      url: req.originalUrl,
      method: req.method,
      params: req.params,
      query: req.query,
    },
    'REST request received');
  next();
});

app.post('/rest/global/appliances', applianceService.post);
app.delete('/rest/global/appliances/:id', applianceService.delete);
app.get('/rest/global/appliances', applianceService.getList);
app.get('/rest/global/appliances/:id', applianceService.get);

app.get('/rest/global/:category', resourceService.getList);
app.get('/rest/global/:category/:id', resourceService.get);

const server = http.createServer(app);
server.listen(PORT);<|endoftext|>