<commit_before>/**
 * Created by longhao on 2017/5/4.
 */
/** @member {Object} */
var winston = require('winston');
var fs = require('fs');
var path = require('path');
/** @member {Object} */
var nconf = require('nconf');
var async = require('async');
var _ = require('lodash');
var cors = require('cors');

var express = require('express');
var app = express();
var server;

var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var useragent = require('express-useragent');
var favicon = require('serve-favicon');

var middleware = require('./server/middleware');

var connectRedis = require("connect-redis")(session);
var storeRedis = new connectRedis({
    host: nconf.get('redis:host'),
    port: nconf.get('redis:port'),
    ttl: nconf.get('redis:ttl'),
    db: 0
});

var utils = require('./server/utils');
var logger = require('./server/logger');
var userAgent = require('./server/socket.io/userAgent');

if (nconf.get('app:ssl')) {
    server = require('https').createServer({
        key: fs.readFileSync(nconf.get('app:ssl').key),
        cert: fs.readFileSync(nconf.get('app:ssl').cert),
    }, app);
} else {
    server = require('http').createServer(app);
}

module.exports.server = server;

server.on('error', function (err) {
    winston.error(err);
    if (err.code === 'EADDRINUSE') {
        winston.error('uuChat address in use, exiting...');
        process.exit(1);
    } else if (err.code === 'EADDRNOTAVAIL') {
        winston.error('uuChat ip address is not avail, exiting...');
        process.exit(1);
    } else {
        throw err;
    }
});

server.sessionStore = function() {
    var redisHost = nconf.get('redis:host');
    if (_.isEmpty(redisHost)) {
        var SequelizeStore = require('connect-session-sequelize')(session.Store);
        var sequelize = require('./server/models/index').sequelize;
        winston.info(sequelize.Message);
        return new SequelizeStore({
            db: sequelize
        });
    } else {
        return storeRedis;
    }
};

module.exports.listen = function () {
    async.waterfall([
        function (next) {
            setupExpress(app, next);
            next();
        },
        function (next) {
            checkRedisStarted(next);
        },
        function (next) {
            expressListen();
            next(null, '');
        }
    ], function (err, result) {
        if (err) {
            switch (err.message) {
                case 'redis-need-start':
                    winston.error('you need to start redis, eg: redis-server /usr/local/redis/redis.conf &');
                    break;
                case 'redis-version-too-lower':
                    winston.error('you redis version is too lower , please update redis version above 3.0.0');
                    break;
                case 'logger-folder-need-create':
                    winston.error('logger folder need create in root directory.');
                default:
                    winston.error(err);
                    break;
            }
            process.exit();
        }
        winston.info("Web server has started");
    });
};

function baseHtmlRoute(app, middlewareDev) {
    app.use(express.static(path.join(__dirname, '../build')));
    //need filter css, js, images files
    app.use(fileFilters);
    app.use(session({
        store: server.sessionStore(),
        secret: nconf.get('socket.io:secretKey'),
        key: nconf.get('socket.io:sessionKey'),
        cookie: setupCookie(),
        resave: false,
        saveUninitialized: true
    }));

    app.get('/', function response(req, res) {
        var html = path.join(__dirname, '../build/app.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/demo', function response(req, res) {
        var html = path.join(__dirname, '../build/customer.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/search', function response(req, res) {
        var html = path.join(__dirname, '../build/search.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/console', function response(req, res) {
        var html = path.join(__dirname, '../build/console.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/console/index', function response(req, res) {
        if (!req.session.csid) {
            res.redirect('/console');
        }
        var html = path.join(__dirname, '../build/console.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/chat', function response(req, res) {
        if (!req.session.csid) {
            res.redirect('/');
        }else {
            var customerSuccess = require('./server/socket.io/customerSuccess');
            var csid = req.session.csid;
            winston.info(req.session);
            if (_.isEmpty(customerSuccess.get(csid))) {
                customerSuccess.create({csid: csid, name: req.session.csName, photo: req.session.photo});
            }
        }
        var html = path.join(__dirname, '../build/app.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/register', function response(req, res) {
        var html = path.join(__dirname, '../build/app.html');
        htmlRender(middlewareDev, res, html);
    });
    var opts = middleware.whiteListOpt();
    opts.credentials = true;
    app.get('/s', cors(opts), function response(req, res) {
        res.setHeader("P3P", "CP=CAO PSA OUR"); // For IE set cookie
        req.inframUrl = req.query.r;
        setupSession(req, res);
        var html = path.join(__dirname, '../build/storage.html');
        htmlRender(middlewareDev, res, html);
    });
}

function htmlRender(middlewareDev, res, html) {
    if (middlewareDev) {
        res.write(middlewareDev.fileSystem.readFileSync(html));
        res.end();
    } else {
        res.render(html);
    }
}

function setupExpress(app, callback) {
    app.set('showStackError', true);
    app.disable('x-powered-by'); // http://expressjs.com/zh-cn/advanced/best-practice-security.html
    app.set('json spaces', process.env.NODE_ENV === 'development' ? 4 : 0);

    app.use('/static/images', express.static(path.join(__dirname, './client/static/images')));
    app.use('/content/upload', express.static(path.join(__dirname, '../content/upload')));
    app.use('/content/avatar', express.static(path.join(__dirname, '../content/avatar')));
    app.use('/public', express.static(path.join(__dirname, '../content/html')));

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(cookieParser(nconf.get('socket.io:secretKey')));

    app.use(useragent.express());
    setupFavicon(app);

    if (global.env === 'development') {
        var webpack = require('webpack');
        var webpackMiddleware = require('webpack-dev-middleware');
        var webpackHotMiddleware = require('webpack-hot-middleware');
        var config = require('../tools/webpack.config.dev.js');
        var compiler = webpack(config);
        var middlewareDev = webpackMiddleware(compiler, {
            publicPath: config.output.publicPath,
            contentBase: 'src',
            stats: {
                colors: true,
                hash: false,
                timings: true,
                chunks: false,
                chunkModules: false,
                modules: false
            }
        });

        app.use(middlewareDev);
        app.use(webpackHotMiddleware(compiler, {
            log: console.log, path: '/__webpack_hmr', heartbeat: 10 * 1000
        }));

        baseHtmlRoute(app, middlewareDev);
    } else {
        baseHtmlRoute(app, null);
        app.enable('cache');
        app.enable('minification');
    }

    app.set('view engine', 'html');
    app.engine('html', require('ejs').renderFile);
    app.enable('view cache');

    var routes = require('./server/routes');
    routes(app, middleware);

    //app.use(middleware.checkAccountPermissions);

    setupAutoLocale(app, callback);

    // catch 404 and forward to error handler
    app.use(function(req, res, next) {
        logger.error("~~~~~~ has 404 error, please see browser console log!");
        res.status(404).send('can not find page!');
    });
    app.use(function(err, req, res, next) {
        if (global.env === 'development') {
            logger.error(err.stack);
        } else {
            logger.error("~~~~~~ has 503 error!");
        }
        res.status(503).send('system has problem.');
    });

    winston.info('setup express success!');
}

function setupFavicon(app) {
    app.use(favicon(path.join(__dirname, 'client/static/images/uuchat.ico')));
}

function setupCookie() {
    var oneMonth = 30 * 86400000;

    var cookie = {
        expires: new Date(Date.now() + oneMonth)
    };

    var relativePath = nconf.get('app:relative_path');
    if (relativePath !== '') {
        cookie.path = relativePath;
    }

    return cookie;
}

function setupSession(req, res) {
    var cid = '';
    var ua = req.useragent;
    if (req.session.cid) {
        cid = req.session.cid;
    } else {
        cid = require('uuid/v4')();  //gen uuid
        req.session.cid = cid;
        ua.needSnycDB = true;
    }

    //res.cookie('uu.c', cid, {expires: new Date(Date.now() + 900000), httpOnly: true, path: '/'});

    var headers = req ? req.headers : {};
    var host = headers.host;
    var referer = headers.referer || '';

    if (!host) {
        var url = require('url');
        host = url.parse(referer).host || '';
    }
    var ip = headers['x-forwarded-for'] || req.connection.remoteAddress;

    ua.cid = cid;
    ua.ip = ip;
    ua.host = host;
    if (req.inframUrl) {
        ua.url = req.inframUrl;
    } else {
        ua.url = req.protocol + '://' + req.get('host') + req.originalUrl;
    }
    userAgent.create(ua);
    winston.info('Customer session had set');
}

function fileFilters(req, res, next) {
    var originalUrl = req.originalUrl;
    var fileFilters = ['css', 'js', 'png', 'jpg', 'jpeg', 'ico'];
    var flag = false;
    var suffix = originalUrl.split('.').pop();

    if (fileFilters.indexOf(suffix) !== -1) {
        flag = true;
    }
    if (flag) {
        res.render(path.join(__dirname, originalUrl));
    } else {
        next();
    }
}

//check redis has started;

function checkRedisStarted(callback){
    var redisHost = nconf.get('redis:host');
    if (!_.isEmpty(redisHost)) {
        utils.lsof(nconf.get('redis:port'), function (data) {
            if (data.length > 0) {
                winston.info('');
                winston.info("[redis] has started");
            } else {
                callback(new Error('redis-need-start'));
            }
        });

        //version print
        if (global.env !== 'development') {
            var _redis = require("../node_modules/connect-redis/node_modules/redis"),
                client = _redis.createClient();
            client.info(function () {
                var info = client.server_info;
                var versions = info.versions;
                if (versions[0] < 3) {
                    callback(new Error('redis-version-too-lower'));
                } else {
                    winston.info("[redis] version = %s", info.redis_version);
                    winston.info("[redis] executable = %s", info.executable);
                    winston.info("[redis] config file = %s", info.config_file);
                    winston.info('');
                }
            });
        }
    }

    callback();
}

function setupAutoLocale(app, callback) {

}

function expressListen() {
    var configAddress = nconf.get('app:address');
    var address = ((configAddress === '0.0.0.0' || !configAddress) ? '0.0.0.0' : configAddress);

    //server.listen.apply(server, args);
    server.listen(nconf.get('app:port'), address, function () {
        process.setMaxListeners(0);
        process.env.TZ = 'Hongkong';
    });
    server.on('listening', function onListening() {
        var addr = server.address();
        var bind = typeof addr === 'string' ?
            'pipe ' + addr :
            'port ' + addr.port;
        winston.info('Listening on ' + bind);
    });
}
<commit_msg>use gzip<commit_after>/**
 * Created by longhao on 2017/5/4.
 */
/** @member {Object} */
var winston = require('winston');
var fs = require('fs');
var path = require('path');
/** @member {Object} */
var nconf = require('nconf');
var async = require('async');
var _ = require('lodash');
var cors = require('cors');

var express = require('express');
var app = express();
var server;

var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var useragent = require('express-useragent');
var favicon = require('serve-favicon');
var compress = require('compression');

var middleware = require('./server/middleware');

var connectRedis = require("connect-redis")(session);
var storeRedis = new connectRedis({
    host: nconf.get('redis:host'),
    port: nconf.get('redis:port'),
    ttl: nconf.get('redis:ttl'),
    db: 0
});

var utils = require('./server/utils');
var logger = require('./server/logger');
var userAgent = require('./server/socket.io/userAgent');

if (nconf.get('app:ssl')) {
    server = require('https').createServer({
        key: fs.readFileSync(nconf.get('app:ssl').key),
        cert: fs.readFileSync(nconf.get('app:ssl').cert),
    }, app);
} else {
    server = require('http').createServer(app);
}

module.exports.server = server;

server.on('error', function (err) {
    winston.error(err);
    if (err.code === 'EADDRINUSE') {
        winston.error('uuChat address in use, exiting...');
        process.exit(1);
    } else if (err.code === 'EADDRNOTAVAIL') {
        winston.error('uuChat ip address is not avail, exiting...');
        process.exit(1);
    } else {
        throw err;
    }
});

server.sessionStore = function() {
    var redisHost = nconf.get('redis:host');
    if (_.isEmpty(redisHost)) {
        var SequelizeStore = require('connect-session-sequelize')(session.Store);
        var sequelize = require('./server/models/index').sequelize;
        winston.info(sequelize.Message);
        return new SequelizeStore({
            db: sequelize
        });
    } else {
        return storeRedis;
    }
};

module.exports.listen = function () {
    async.waterfall([
        function (next) {
            setupExpress(app, next);
            next();
        },
        function (next) {
            checkRedisStarted(next);
        },
        function (next) {
            expressListen();
            next(null, '');
        }
    ], function (err, result) {
        if (err) {
            switch (err.message) {
                case 'redis-need-start':
                    winston.error('you need to start redis, eg: redis-server /usr/local/redis/redis.conf &');
                    break;
                case 'redis-version-too-lower':
                    winston.error('you redis version is too lower , please update redis version above 3.0.0');
                    break;
                case 'logger-folder-need-create':
                    winston.error('logger folder need create in root directory.');
                default:
                    winston.error(err);
                    break;
            }
            process.exit();
        }
        winston.info("Web server has started");
    });
};

function baseHtmlRoute(app, middlewareDev) {
    app.use(express.static(path.join(__dirname, '../build')));
    //need filter css, js, images files
    app.use(fileFilters);
    app.use(session({
        store: server.sessionStore(),
        secret: nconf.get('socket.io:secretKey'),
        key: nconf.get('socket.io:sessionKey'),
        cookie: setupCookie(),
        resave: false,
        saveUninitialized: true
    }));

    app.get('/', function response(req, res) {
        var html = path.join(__dirname, '../build/app.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/demo', function response(req, res) {
        var html = path.join(__dirname, '../build/customer.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/search', function response(req, res) {
        var html = path.join(__dirname, '../build/search.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/console', function response(req, res) {
        var html = path.join(__dirname, '../build/console.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/console/index', function response(req, res) {
        if (!req.session.csid) {
            res.redirect('/console');
        }
        var html = path.join(__dirname, '../build/console.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/chat', function response(req, res) {
        if (!req.session.csid) {
            res.redirect('/');
        }else {
            var customerSuccess = require('./server/socket.io/customerSuccess');
            var csid = req.session.csid;
            winston.info(req.session);
            if (_.isEmpty(customerSuccess.get(csid))) {
                customerSuccess.create({csid: csid, name: req.session.csName, photo: req.session.photo});
            }
        }
        var html = path.join(__dirname, '../build/app.html');
        htmlRender(middlewareDev, res, html);
    });
    app.get('/register', function response(req, res) {
        var html = path.join(__dirname, '../build/app.html');
        htmlRender(middlewareDev, res, html);
    });
    var opts = middleware.whiteListOpt();
    opts.credentials = true;
    app.get('/s', cors(opts), function response(req, res) {
        res.setHeader("P3P", "CP=CAO PSA OUR"); // For IE set cookie
        req.inframUrl = req.query.r;
        setupSession(req, res);
        var html = path.join(__dirname, '../build/storage.html');
        htmlRender(middlewareDev, res, html);
    });
}

function htmlRender(middlewareDev, res, html) {
    if (middlewareDev) {
        res.write(middlewareDev.fileSystem.readFileSync(html));
        res.end();
    } else {
        res.render(html);
    }
}

function setupExpress(app, callback) {
    app.set('showStackError', true);
    app.disable('x-powered-by'); // http://expressjs.com/zh-cn/advanced/best-practice-security.html
    app.set('json spaces', process.env.NODE_ENV === 'development' ? 4 : 0);

    app.use('/static/images', express.static(path.join(__dirname, './client/static/images')));
    app.use('/content/upload', express.static(path.join(__dirname, '../content/upload')));
    app.use('/content/avatar', express.static(path.join(__dirname, '../content/avatar')));
    app.use('/public', express.static(path.join(__dirname, '../content/html')));

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(cookieParser(nconf.get('socket.io:secretKey')));

    app.use(useragent.express());
    setupFavicon(app);
    app.use(compress());
    if (global.env === 'development') {
        var webpack = require('webpack');
        var webpackMiddleware = require('webpack-dev-middleware');
        var webpackHotMiddleware = require('webpack-hot-middleware');
        var config = require('../tools/webpack.config.dev.js');
        var compiler = webpack(config);
        var middlewareDev = webpackMiddleware(compiler, {
            publicPath: config.output.publicPath,
            contentBase: 'src',
            stats: {
                colors: true,
                hash: false,
                timings: true,
                chunks: false,
                chunkModules: false,
                modules: false
            }
        });

        app.use(middlewareDev);
        app.use(webpackHotMiddleware(compiler, {
            log: console.log, path: '/__webpack_hmr', heartbeat: 10 * 1000
        }));

        baseHtmlRoute(app, middlewareDev);
    } else {
        baseHtmlRoute(app, null);
        app.enable('cache');
        app.enable('minification');
    }

    app.set('view engine', 'html');
    app.engine('html', require('ejs').renderFile);
    app.enable('view cache');

    var routes = require('./server/routes');
    routes(app, middleware);

    //app.use(middleware.checkAccountPermissions);

    setupAutoLocale(app, callback);

    // catch 404 and forward to error handler
    app.use(function(req, res, next) {
        logger.error("~~~~~~ has 404 error, please see browser console log!");
        res.status(404).send('can not find page!');
    });
    app.use(function(err, req, res, next) {
        if (global.env === 'development') {
            logger.error(err.stack);
        } else {
            logger.error("~~~~~~ has 503 error!");
        }
        res.status(503).send('system has problem.');
    });

    winston.info('setup express success!');
}

function setupFavicon(app) {
    app.use(favicon(path.join(__dirname, 'client/static/images/uuchat.ico')));
}

function setupCookie() {
    var oneMonth = 30 * 86400000;

    var cookie = {
        expires: new Date(Date.now() + oneMonth)
    };

    var relativePath = nconf.get('app:relative_path');
    if (relativePath !== '') {
        cookie.path = relativePath;
    }

    return cookie;
}

function setupSession(req, res) {
    var cid = '';
    var ua = req.useragent;
    if (req.session.cid) {
        cid = req.session.cid;
    } else {
        cid = require('uuid/v4')();  //gen uuid
        req.session.cid = cid;
        ua.needSnycDB = true;
    }

    //res.cookie('uu.c', cid, {expires: new Date(Date.now() + 900000), httpOnly: true, path: '/'});

    var headers = req ? req.headers : {};
    var host = headers.host;
    var referer = headers.referer || '';

    if (!host) {
        var url = require('url');
        host = url.parse(referer).host || '';
    }
    var ip = headers['x-forwarded-for'] || req.connection.remoteAddress;

    ua.cid = cid;
    ua.ip = ip;
    ua.host = host;
    if (req.inframUrl) {
        ua.url = req.inframUrl;
    } else {
        ua.url = req.protocol + '://' + req.get('host') + req.originalUrl;
    }
    userAgent.create(ua);
    winston.info('Customer session had set');
}

function fileFilters(req, res, next) {
    var originalUrl = req.originalUrl;
    var fileFilters = ['css', 'js', 'png', 'jpg', 'jpeg', 'ico'];
    var flag = false;
    var suffix = originalUrl.split('.').pop();

    if (fileFilters.indexOf(suffix) !== -1) {
        flag = true;
    }
    if (flag) {
        res.render(path.join(__dirname, originalUrl));
    } else {
        next();
    }
}

//check redis has started;

function checkRedisStarted(callback){
    var redisHost = nconf.get('redis:host');
    if (!_.isEmpty(redisHost)) {
        utils.lsof(nconf.get('redis:port'), function (data) {
            if (data.length > 0) {
                winston.info('');
                winston.info("[redis] has started");
            } else {
                callback(new Error('redis-need-start'));
            }
        });

        //version print
        if (global.env !== 'development') {
            var _redis = require("../node_modules/connect-redis/node_modules/redis"),
                client = _redis.createClient();
            client.info(function () {
                var info = client.server_info;
                var versions = info.versions;
                if (versions[0] < 3) {
                    callback(new Error('redis-version-too-lower'));
                } else {
                    winston.info("[redis] version = %s", info.redis_version);
                    winston.info("[redis] executable = %s", info.executable);
                    winston.info("[redis] config file = %s", info.config_file);
                    winston.info('');
                }
            });
        }
    }

    callback();
}

function setupAutoLocale(app, callback) {

}

function expressListen() {
    var configAddress = nconf.get('app:address');
    var address = ((configAddress === '0.0.0.0' || !configAddress) ? '0.0.0.0' : configAddress);

    //server.listen.apply(server, args);
    server.listen(nconf.get('app:port'), address, function () {
        process.setMaxListeners(0);
        process.env.TZ = 'Hongkong';
    });
    server.on('listening', function onListening() {
        var addr = server.address();
        var bind = typeof addr === 'string' ?
            'pipe ' + addr :
            'port ' + addr.port;
        winston.info('Listening on ' + bind);
    });
}
<|endoftext|>


<commit_before>'use strict';

function fastbootExpressMiddleware(distPath, options) {
  let opts = options;

  if (arguments.length === 1) {
    if (typeof distPath === 'string') {
      opts = { distPath: distPath };
    } else {
      opts = distPath;
    }
  }

  opts = opts || {};

  let log = opts.log !== false ? _log : function() {};

  let fastboot = opts.fastboot;

  if (!fastboot) {
    let FastBoot = require('fastboot');
    fastboot = new FastBoot({
      distPath: opts.distPath,
      resilient: opts.resilient,
    });
  }

  return async function(req, res, next) {
    let path = req.url;

    try {
      let result = await fastboot.visit(path, { request: req, response: res });
      let body = opts.chunkedResponse ? await result.chunks() : await result.html();

      if (result.error) {
        log('RESILIENT MODE CAUGHT:', result.error.stack);
        next(result.error);
        return;
      }

      let headers = result.headers;
      let statusMessage = result.error ? 'NOT OK ' : 'OK ';

      for (var pair of headers.entries()) {
        res.append(pair[0], pair[1]);
      }

      log(result.statusCode, statusMessage + path);
      res.status(result.statusCode);

      if (typeof body === 'string') {
        res.send(body);
      } else if (result.error) {
        res.send(body[0]);
      } else {
        body.forEach(chunk => res.write(chunk));
        res.end();
      }
    } catch (error) {
      if (error.name === 'UnrecognizedURLError') {
        next();
      } else {
        res.status(500);
        next(error);
      }
    }
  };
}

let chalk;

function _log(statusCode, message, startTime) {
  chalk = chalk || require('chalk');
  let color = statusCode === 200 ? 'green' : 'red';
  let now = new Date();

  if (startTime) {
    let diff = Date.now() - startTime;
    message = message + chalk.blue(' ' + diff + 'ms');
  }

  console.log(chalk.blue(now.toISOString()) + ' ' + chalk[color](statusCode) + ' ' + message);
}

module.exports = fastbootExpressMiddleware;
<commit_msg>Restart resilient mode behavior<commit_after>'use strict';

function fastbootExpressMiddleware(distPath, options) {
  let opts = options;

  if (arguments.length === 1) {
    if (typeof distPath === 'string') {
      opts = { distPath: distPath };
    } else {
      opts = distPath;
    }
  }

  opts = opts || {};

  let log = opts.log !== false ? _log : function() {};

  let fastboot = opts.fastboot;

  if (!fastboot) {
    let FastBoot = require('fastboot');
    fastboot = new FastBoot({
      distPath: opts.distPath,
      resilient: opts.resilient,
    });
  }

  return async function(req, res, next) {
    let path = req.url;

    try {
      let result = await fastboot.visit(path, { request: req, response: res });
      let body = opts.chunkedResponse ? await result.chunks() : await result.html();

      if (result.error) {
        log('RESILIENT MODE CAUGHT:', result.error.stack);
        next(result.error);
      }

      let headers = result.headers;
      let statusMessage = result.error ? 'NOT OK ' : 'OK ';

      for (var pair of headers.entries()) {
        res.append(pair[0], pair[1]);
      }

      log(result.statusCode, statusMessage + path);
      res.status(result.statusCode);

      if (typeof body === 'string') {
        res.send(body);
      } else if (result.error) {
        res.send(body[0]);
      } else {
        body.forEach(chunk => res.write(chunk));
        res.end();
      }
    } catch (error) {
      if (error.name === 'UnrecognizedURLError') {
        next();
      } else {
        res.status(500);
        next(error);
      }
    }
  };
}

let chalk;

function _log(statusCode, message, startTime) {
  chalk = chalk || require('chalk');
  let color = statusCode === 200 ? 'green' : 'red';
  let now = new Date();

  if (startTime) {
    let diff = Date.now() - startTime;
    message = message + chalk.blue(' ' + diff + 'ms');
  }

  console.log(chalk.blue(now.toISOString()) + ' ' + chalk[color](statusCode) + ' ' + message);
}

module.exports = fastbootExpressMiddleware;
<|endoftext|>


<commit_before>import readGlob from 'read-glob-promise';
import {match, trim, exclude, unique, alphabetically} from './utils';

/**
 * Gather the package names of
 * the dependencies registered
 * in your package.json
 *
 * @param projectConfig
 * @param locations
 * @returns {Array}
 */
export function getRegisteredDependencies(projectConfig, locations) {
	return locations.reduce(
			(packages, key) => projectConfig[key]
					? packages.concat(Object.keys(projectConfig[key]))
					: packages
			, []);
}

/**
 * Gather the package names of
 * the dependencies used in the
 * given codebase
 *
 * @param glob
 * @param matchRegex
 * @param trimRegex
 * @returns {*}
 */
export function getUsedDependencies(glob, matchRegex, trimRegex) {
	return readGlob(glob, 'utf8')
		.then(contents =>
			contents
				.reduce(match(matchRegex), [])
				.filter(unique)
				.map(trim(trimRegex))
				.sort(alphabetically)
		);
}

/**
 *
 * @param registeredDependencies
 * @param usedDependencies
 * @param exclusions
 * @returns {*}
 */
export function getUnusedDependencies(registeredDependencies, usedDependencies, exclusions = []) {
	return registeredDependencies
		.filter(exclude(exclusions))
		.filter(exclude(usedDependencies));
}

/**
 * Approximately list packages that are
 * registered in your package json but
 * not used in your code
 *
 * @param glob - the files to read to determine actual used packages
 * @param matchRegex -
 * @param trimRegex -
 * @param locations -
 * @param excluded -
 * @param projectConfig -
 */
export default function unusedDependencies(glob, {
	// the regex to use to extract all the explicit
	// dependency uses from the codebase
	matchRegex = /require\(('|")[a-z0-9\-_\\/]+('|")\)/gi,

	// the regex to use to trim the
	// matched strings
	trimRegex = /(require\()|('|")|\)/gi,

	// the package.json keys to use to determine
	// registered dependencies
	locations = ['dependencies', 'devDependencies'],

	// any packages you would want to exclude
	// from the final list
	excluded = [],

	// package json
	projectConfig = require('./package.json')
} = {}) {
	getUsedDependencies(glob, matchRegex, trimRegex)
		.then(log('used packages:'))
		.then(usedPackages =>
			getRegisteredDependencies(projectConfig, locations)
				.filter(exclude(usedPackages))
				.filter(exclude(excluded))
		)
		.then(log('registered but not explicitly used packages:'))
		.catch(err => console.error(err));
}
<commit_msg>fix regexes<commit_after>import readGlob from 'read-glob-promise';
import {match, trim, exclude, unique, alphabetically} from './utils';

/**
 * Gather the package names of
 * the dependencies registered
 * in your package.json
 *
 * @param projectConfig
 * @param locations
 * @returns {Array}
 */
export function getRegisteredDependencies(projectConfig, locations) {
	return locations.reduce(
			(packages, key) => projectConfig[key]
					? packages.concat(Object.keys(projectConfig[key]))
					: packages
			, []);
}

/**
 * Gather the package names of
 * the dependencies used in the
 * given codebase
 *
 * @param glob
 * @param matchRegex
 * @param trimRegex
 * @returns {*}
 */
export function getUsedDependencies(glob, matchRegex, trimRegex) {
	return readGlob(glob, 'utf8')
		.then(contents =>
			contents
				.reduce(match(matchRegex), [])
				.filter(unique)
				.map(trim(trimRegex))
				.sort(alphabetically)
		);
}

/**
 *
 * @param registeredDependencies
 * @param usedDependencies
 * @param exclusions
 * @returns {*}
 */
export function getUnusedDependencies(registeredDependencies, usedDependencies, exclusions = []) {
	return registeredDependencies
		.filter(exclude(exclusions))
		.filter(exclude(usedDependencies));
}

/**
 * Approximately list packages that are
 * registered in your package json but
 * not used in your code
 *
 * @param glob - the files to read to determine actual used packages
 * @param matchRegex -
 * @param trimRegex -
 * @param locations -
 * @param excluded -
 * @param projectConfig -
 */
export default function unusedDependencies(glob, {
	// the regex to use to extract all the explicit
	// dependency uses from the codebase
	matchRegex = (/require\(('|")[a-z0-9\-_\\/]+('|")\)/gi),

	// the regex to use to trim the
	// matched strings
	trimRegex = (/(require\()|('|")|\)/gi),

	// the package.json keys to use to determine
	// registered dependencies
	locations = ['dependencies', 'devDependencies'],

	// any packages you would want to exclude
	// from the final list
	excluded = [],

	// package json
	projectConfig = require('./package.json')
} = {}) {
	getUsedDependencies(glob, matchRegex, trimRegex)
		.then(log('used packages:'))
		.then(usedPackages =>
			getRegisteredDependencies(projectConfig, locations)
				.filter(exclude(usedPackages))
				.filter(exclude(excluded))
		)
		.then(log('registered but not explicitly used packages:'))
		.catch(err => console.error(err));
}
<|endoftext|>


<commit_before>import Reflect from 'core-js/fn/reflect';

const clone = tree => tree.match(
	{attrs: {class: /.+/}},
	node => Object.assign(node, Object.assign(node.attrs, {'css-module': node.attrs.class}))
);

const removeClass = tree => tree.match(
	{attrs: {class: /.+/}},
	node => {
		console.log(node);
		delete node.attrs.class;

		return node;
	}
);

const cloneClassTo = (tree, options) => Promise.resolve(tree)
	.then(tree => clone(tree))
	.then(tree => (Reflect.has(options, 'removeClass') && options.removeClass) ? removeClass(tree) : tree)
	.then(tree => tree);

export default (options = {}) => {
	return tree => new Promise((resolve, reject) => {
		if (!Array.isArray(tree)) {
			reject(new Error(`tree is not Array`));
		}

		if (tree.length === 0) {
			resolve(tree);
		}

		resolve(cloneClassTo(tree, options));
	});
};
<commit_msg>fix(index): fix remove class<commit_after>import Reflect from 'core-js/fn/reflect';

const clone = tree => tree.match(
	{attrs: {class: /.+/}},
	node => {
		node.attrs = Object.assign(node.attrs, {'css-module': node.attrs.class});

		return node;
	}
);

const removeClass = tree => tree.match(
	{attrs: {class: /.+/}},
	node => {
		node.attrs = Object.keys(node.attrs)
			.reduce((attrs, key) => Object.assign(attrs, key === 'class' ? {} : {[key]: node.attrs[key]}), {});

		return node;
	}
);

const cloneClassTo = (tree, options) => Promise.resolve(tree)
	.then(tree => clone(tree))
	.then(tree => (Reflect.has(options, 'removeClass') && options.removeClass) ? removeClass(tree) : tree)
	.then(tree => tree);

export default (options = {}) => {
	return tree => new Promise((resolve, reject) => {
		if (!Array.isArray(tree)) {
			reject(new Error(`tree is not Array`));
		}

		if (tree.length === 0) {
			resolve(tree);
		}

		resolve(cloneClassTo(tree, options));
	});
};
<|endoftext|>


<commit_before>import fs from "fs"
import path from "path"
import crypto from "crypto"
import denodeify from "denodeify"
import fse from "fs-extra"
import { getHashDigest } from "loader-utils"
import { createFilter } from "rollup-pluginutils"

import postcss from "postcss"
import postcssSmartImport from "postcss-smart-import"
import postcssSimpleUrl from "postcss-simple-url"
import postcssParserSugarss from "sugarss"
import postcssParserScss from "postcss-scss"

var copyAsync = denodeify(fse.copy)
var writeAsync = denodeify(fse.outputFile)

const styleExtensions =
{
  ".css": null,
  ".sss": postcssParserSugarss,
  ".scss": postcssParserScss
}

const postcssPlugins = [
  postcssSmartImport(),
  postcssSimpleUrl()
]

function processStyle(code, id, dest)
{
  var parser = styleExtensions[path.extname(id)]
  return postcss(postcssPlugins)
    .process(code,
    {
      from: id,
      to: dest,
      parser: parser,
      extensions: [ ".css", ".sss", ".scss" ]
    })
    .then((result) => {
      return writeAsync(dest, result)
    })
    .catch((err) => {
      console.error(err)
    })
}

const hashType = "sha256"
const digestType = "base62"
const digestLength = 8

const externalIds = {}

const defaultExclude =
[
  "**/*.json",
  "**/*.js",
  "**/*.jsx",
  "**/*.ts",
  "**/*.tsx",
  "**/*.es",
  "**/*.es5",
  "**/*.es6",
  "**/*.es7",
  "**/*.vue"
]

export default function relink(options = {})
{
  const { limit, include, exclude = defaultExclude, entry, outputFolder, verbose } = options
  const filter = createFilter(include, exclude)

  return {
    name: "rollup-plugin-relink",

    isExternal: function(id)
    {
      var baseName = "./" + path.basename(id)
      return baseName in externalIds
    },

    resolveId: function(importee)
    {
      if (importee in externalIds)
      {
        // This does not yet seem to work!
        // See also: https://github.com/rollup/rollup/issues/861
        // "returning any other falsy value signals that importee should be treated as an external module
        // and not included in the bundle." -- https://github.com/rollup/rollup/wiki/Plugins#creating-plugins
        return false
      }

      return null
    },

    load: function(id)
    {
      if (!filter(id))
        return null

      const input = fs.createReadStream(id)
      const hash = crypto.createHash("sha256")

      return new Promise((resolve, reject) =>
      {
        input.on("readable", () =>
        {
          var fileSource = id
          var fileContent = fs.readFileSync(fileSource)
          var fileExt = path.extname(id)
          var fileHash = getHashDigest(fileContent, hashType, digestType, digestLength)

          var destExt = fileExt in styleExtensions ? ".css" : fileExt
          var destId = path.basename(id, fileExt) + "-" + fileHash + destExt

          var fileDest = path.resolve(outputFolder, destId)

          // Mark new file location as external to prevent further processing.
          externalIds["./" + destId] = true

          var entryFolder = path.dirname(path.resolve(entry))
          var relativeToRoot = path.relative(path.dirname(fileSource), entryFolder)

          // Adjust destId so that it points to the root folder - from any
          // depth we detected inside the original project structure.
          var importId = (relativeToRoot ? relativeToRoot + "/" : "./") + destId

          if (fileExt in styleExtensions)
          {
            if (verbose)
              console.log(`Processing ${fileSource} => ${fileDest}...`)

            return processStyle(fileContent, fileSource, fileDest).then(() =>
            {
              resolve({
                code: `import _${fileHash} from "${importId}"; export default _${fileHash};`,
                map: { mappings: "" }
              })
            })
          }
          else
          {
            if (verbose)
              console.log(`Copying ${fileSource} => ${fileDest}...`)

            return copyAsync(fileSource, fileDest).then(() =>
            {
              resolve({
                code: `import _${fileHash} from "${importId}"; export default _${fileHash};`,
                map: { mappings: "" }
              })
            })
          }
        })
      })
    }
  }
}
<commit_msg>Fixed importID generation so that asset imports are correctly handled.<commit_after>import fs from "fs"
import path from "path"
import crypto from "crypto"
import denodeify from "denodeify"
import fse from "fs-extra"
import { getHashDigest } from "loader-utils"
import { createFilter } from "rollup-pluginutils"

import postcss from "postcss"
import postcssSmartImport from "postcss-smart-import"
import postcssSimpleUrl from "postcss-simple-url"
import postcssParserSugarss from "sugarss"
import postcssParserScss from "postcss-scss"

var copyAsync = denodeify(fse.copy)
var writeAsync = denodeify(fse.outputFile)

const styleExtensions =
{
  ".css": null,
  ".sss": postcssParserSugarss,
  ".scss": postcssParserScss
}

const postcssPlugins = [
  postcssSmartImport(),
  postcssSimpleUrl()
]

function processStyle(code, id, dest)
{
  var parser = styleExtensions[path.extname(id)]
  return postcss(postcssPlugins)
    .process(code,
    {
      from: id,
      to: dest,
      parser: parser,
      extensions: [ ".css", ".sss", ".scss" ]
    })
    .then((result) => {
      return writeAsync(dest, result)
    })
    .catch((err) => {
      console.error(err)
    })
}

const hashType = "sha256"
const digestType = "base62"
const digestLength = 8

const externalIds = {}

const defaultExclude =
[
  "**/*.json",
  "**/*.js",
  "**/*.jsx",
  "**/*.ts",
  "**/*.tsx",
  "**/*.es",
  "**/*.es5",
  "**/*.es6",
  "**/*.es7",
  "**/*.vue"
]

export default function relink(options = {})
{
  const { limit, include, exclude = defaultExclude, entry, outputFolder, verbose } = options
  const filter = createFilter(include, exclude)

  return {
    name: "rollup-plugin-relink",

    isExternal: function(id)
    {
      var baseName = "./" + path.basename(id)
      return baseName in externalIds
    },

    resolveId: function(importee)
    {
      if (importee in externalIds)
      {
        // This does not yet seem to work!
        // See also: https://github.com/rollup/rollup/issues/861
        // "returning any other falsy value signals that importee should be treated as an external module
        // and not included in the bundle." -- https://github.com/rollup/rollup/wiki/Plugins#creating-plugins
        return false
      }

      return null
    },

    load: function(id)
    {
      if (!filter(id))
        return null

      const input = fs.createReadStream(id)
      const hash = crypto.createHash("sha256")

      return new Promise((resolve, reject) =>
      {
        input.on("readable", () =>
        {
          var fileSource = id
          var fileContent = fs.readFileSync(fileSource)
          var fileExt = path.extname(id)
          var fileHash = getHashDigest(fileContent, hashType, digestType, digestLength)

          var destExt = fileExt in styleExtensions ? ".css" : fileExt
          var destId = path.basename(id, fileExt) + "-" + fileHash + destExt

          var fileDest = path.resolve(outputFolder, destId)

          // Mark new file location as external to prevent further processing.
          externalIds["./" + destId] = true

          var entryFolder = path.dirname(path.resolve(entry))
          var relativeToRoot = path.relative(path.dirname(fileSource), entryFolder)

          // Adjust destId so that it points to the root folder - from any
          // depth we detected inside the original project structure.
          if (relativeToRoot.charAt(0) === ".") {
            var importId = relativeToRoot + "/" + destId;
          } else if (relativeToRoot === "") {
            var importId = "./" + destId;
          } else {
            var importId = "./" + relativeToRoot + "/" + destId;
          }

          if (fileExt in styleExtensions)
          {
            if (verbose)
              console.log(`Processing ${fileSource} => ${fileDest}...`)

            return processStyle(fileContent, fileSource, fileDest).then(() =>
            {
              resolve({
                code: `import _${fileHash} from "${importId}"; export default _${fileHash};`,
                map: { mappings: "" }
              })
            })
          }
          else
          {
            if (verbose)
              console.log(`Copying ${fileSource} => ${fileDest}...`)

            return copyAsync(fileSource, fileDest).then(() =>
            {
              resolve({
                code: `import _${fileHash} from "${importId}"; export default _${fileHash};`,
                map: { mappings: "" }
              })
            })
          }
        })
      })
    }
  }
}
<|endoftext|>


<commit_before>var q = require('q');
var leAsymmetricEncryption = require('@castle/le-asymmetric-encryption');
var LeAsymmetricEncryptionService = new leAsymmetricEncryption.LeAsymmetricEncryptionService();
/**
 * A tool for creating and processing background jobs
 * @class JobQueueService
 * @param {StorageService} storage an instance of le-storage-service that is used to create records
 * @param {string} type the type of queue you want to create, supported types are 'default', 'session', and 'fast', leaving the field undefined is the same as 'default'
 * @returns {service}
 */
var JobQueueService = function (storage, type) {
  if (!storage) { throw new Error('Instance of storage service required'); }
  if (type !== 'session' && type !== 'fast' && type !== 'default' && type !== undefined) {
    throw new Error('Invalid value for the type param, value: ' + type);
  }
  var queueType = type;
  var _storage = storage;
  var _provider;
  /**
   * Stores a new job to process
   * @function addJob
   * @memberof JobQueueService
   * @instance
   * @param {string} type the type of the job, used to determine how it should be processed
   * @param {string} data the data necessary to complete the job
   * @returns {promise} resolves with the newly created job record
   */
  this.addJob = function (type, data, sensitiveData) {
    var _this = this;
    var promiseChain = q.resolve();
    return promiseChain.then(function () {
      if (!this.publicKey && sensitiveData) {
        return _this.fetchPublicKey();
      }
    }).then(function () {
      if (sensitiveData) {
        sensitiveData = JSON.stringify(sensitiveData);
        var encryptedData = LeAsymmetricEncryptionService.encrypt(sensitiveData, this.publicKey);
        data.encryptedData = encryptedData;
      }
      var record;
      if (queueType === 'fast') {
        record = _storage.createRecord('_fastQueue/task');
      } else if (queueType === 'session') {
        record = _storage.createRecord('_sessionQueue/task');
      } else {
        record = _storage.createRecord('_queue/task');
      }
      return record.update({
        type: type,
        data: data
      })
    }).then(function () {
      return record;
    });
  }
  this.fetchPublicKey = function () {
    return _storage.fetchRecord('Public Key', 'BACKGROUND_PUBLIC_KEY').then(function (publicKeyRecord) {
      var publicKeyRecordData = publicKeyRecord.getData();
      this.publicKey = publicKeyRecordData.value;
    });
  }
  /**
   * Stores a new job and resolve when the job is complete
   * @function performJob
   * @memberof JobQueueService
   * @instance
   * @param {string} type the type of the job, used to determine how it should be processed
   * @param {string} data the data necessary to complete the job
   * @returns {promise} resolves when the task is complete
   */
  this.performJob = function (type, data) {
    var deferred = q.defer();
    this.addJob(type, data)
    .then(function (record) {
      record.sync(function (recordData) {
        if (recordData === null) {
          record.unsync();
          deferred.resolve();
        }
      });
    });
    return deferred.promise;
  }
  /**
   * Creates a worker to process the jobs in the queue
   * @function createWorker
   * @memberof JobQueueService
   * @instance
   * @param {JobQueueProvider} provider the provider this service delegates to
   * @param {Function}  processJob function that processes the job. Called with two params `job` and `complete`. This function must call `complete()` to finish processing a job
   */
  this.createWorker = function (provider, processJob, privateKey) {
    if (!provider) { throw new Error('Job queue provider required'); }
    if (!processJob) { throw new Error('Process job callback required'); }
    var innerProcessJob = function (job, complete) {
      var decryptedDataJson = LeAsymmetricEncryptionService.decrypt(job.encryptedData, privateKey);
      var decryptedData = JSON.parse(decryptedData);
      Object.assign(job.data, decryptedData)
      processJob(job, complete);
    }
    _provider = provider;
    _provider.createWorker(innerProcessJob);
  }
  /**
   * Prevents the worker from picking up new jobs and resolves once current jobs are complete
   * @function shutdown
   * @memberof JobQueueService
   * @instance
   * @returns {promise}
   */
  this.shutdown = function () {
    if (!_provider) { throw new Error('Job queue provider required'); }
    return _provider.shutdown();
  }
}

module.exports = JobQueueService;
<commit_msg>fix(addJob): Fix scope issue<commit_after>var q = require('q');
var leAsymmetricEncryption = require('@castle/le-asymmetric-encryption');
var LeAsymmetricEncryptionService = new leAsymmetricEncryption.LeAsymmetricEncryptionService();
/**
 * A tool for creating and processing background jobs
 * @class JobQueueService
 * @param {StorageService} storage an instance of le-storage-service that is used to create records
 * @param {string} type the type of queue you want to create, supported types are 'default', 'session', and 'fast', leaving the field undefined is the same as 'default'
 * @returns {service}
 */
var JobQueueService = function (storage, type) {
  if (!storage) { throw new Error('Instance of storage service required'); }
  if (type !== 'session' && type !== 'fast' && type !== 'default' && type !== undefined) {
    throw new Error('Invalid value for the type param, value: ' + type);
  }
  var queueType = type;
  var _storage = storage;
  var _provider;
  /**
   * Stores a new job to process
   * @function addJob
   * @memberof JobQueueService
   * @instance
   * @param {string} type the type of the job, used to determine how it should be processed
   * @param {string} data the data necessary to complete the job
   * @returns {promise} resolves with the newly created job record
   */
  this.addJob = function (type, data, sensitiveData) {
    var _this = this;
    var promiseChain = q.resolve();
    return promiseChain.then(function () {
      if (!this.publicKey && sensitiveData) {
        return _this.fetchPublicKey();
      }
    }).then(function () {
      if (sensitiveData) {
        sensitiveData = JSON.stringify(sensitiveData);
        var encryptedData = LeAsymmetricEncryptionService.encrypt(sensitiveData, this.publicKey);
        data.encryptedData = encryptedData;
      }
      var record;
      if (queueType === 'fast') {
        record = _storage.createRecord('_fastQueue/task');
      } else if (queueType === 'session') {
        record = _storage.createRecord('_sessionQueue/task');
      } else {
        record = _storage.createRecord('_queue/task');
      }
      return record.update({
        type: type,
        data: data
      })
    }).then(function (record) {
      return record;
    });
  }
  this.fetchPublicKey = function () {
    return _storage.fetchRecord('Public Key', 'BACKGROUND_PUBLIC_KEY').then(function (publicKeyRecord) {
      var publicKeyRecordData = publicKeyRecord.getData();
      this.publicKey = publicKeyRecordData.value;
    });
  }
  /**
   * Stores a new job and resolve when the job is complete
   * @function performJob
   * @memberof JobQueueService
   * @instance
   * @param {string} type the type of the job, used to determine how it should be processed
   * @param {string} data the data necessary to complete the job
   * @returns {promise} resolves when the task is complete
   */
  this.performJob = function (type, data) {
    var deferred = q.defer();
    this.addJob(type, data)
    .then(function (record) {
      record.sync(function (recordData) {
        if (recordData === null) {
          record.unsync();
          deferred.resolve();
        }
      });
    });
    return deferred.promise;
  }
  /**
   * Creates a worker to process the jobs in the queue
   * @function createWorker
   * @memberof JobQueueService
   * @instance
   * @param {JobQueueProvider} provider the provider this service delegates to
   * @param {Function}  processJob function that processes the job. Called with two params `job` and `complete`. This function must call `complete()` to finish processing a job
   */
  this.createWorker = function (provider, processJob, privateKey) {
    if (!provider) { throw new Error('Job queue provider required'); }
    if (!processJob) { throw new Error('Process job callback required'); }
    var innerProcessJob = function (job, complete) {
      var decryptedDataJson = LeAsymmetricEncryptionService.decrypt(job.encryptedData, privateKey);
      var decryptedData = JSON.parse(decryptedData);
      Object.assign(job.data, decryptedData)
      processJob(job, complete);
    }
    _provider = provider;
    _provider.createWorker(innerProcessJob);
  }
  /**
   * Prevents the worker from picking up new jobs and resolves once current jobs are complete
   * @function shutdown
   * @memberof JobQueueService
   * @instance
   * @returns {promise}
   */
  this.shutdown = function () {
    if (!_provider) { throw new Error('Job queue provider required'); }
    return _provider.shutdown();
  }
}

module.exports = JobQueueService;
<|endoftext|>


<commit_before>/* @flow */

/*
 * Types
 */

type CSSClass = string;

type Elements = Array<Element>;

type PredicateFn = (element: Element) => boolean;

type Selector = string;

/*
 * Utilities
 */

function toArray(arrayLike: any): Array<any> {
  return Array.prototype.slice.call(arrayLike);
}

/*
 * Queries
 */

function query(element: Element, selector: Selector): ?Element {
  return element.querySelector(selector);
}

function queryAll(element: Element, selector: Selector): Elements {
  const elements = element.querySelectorAll(selector);

  return (toArray(elements): Elements);
}

type MatchesFn = (selector: Selector) => boolean;

function getMatchesFn(): MatchesFn {
  const element = (document.createElement("div"): any);

  return (
    element.matches ||
    element.matchesSelector ||
    element.msMatchesSelector ||
    element.mozMatchesSelector ||
    element.webkitMatchesSelector ||
    element.oMatchesSelector
  );
}

const matchesFn: MatchesFn = getMatchesFn();

function matches(element: Element, selector: Selector): boolean {
  return matchesFn.call(element, selector);
}

/*
 * Classes
 */

function hasClass(element: Element, cssClass: CSSClass): boolean {
  return element.classList.contains(cssClass);
}

function addClass(element: Element, cssClass: CSSClass): boolean {
  const result = !hasClass(element, cssClass);

  if (result) {
    element.classList.add(cssClass);
  }

  return result;
}

function removeClass(element: Element, cssClass: CSSClass): boolean {
  const result = hasClass(element, cssClass);

  if (result) {
    element.classList.remove(cssClass);
  }

  return result;
}

function toggleClass(
  element: Element,
  cssClass: CSSClass,
  state?: boolean
): boolean {
  const target = arguments.length === 3 ? state : !hasClass(element, cssClass);
  const toggleFn = target ? addClass : removeClass;

  return toggleFn(element, cssClass);
}

/*
 * Dataset
 */

type Dataset = { [key: string]: string };

type DatasetFn = (element: HTMLElement) => Dataset;

function nativeDataset(element: HTMLElement): Dataset {
  return element.dataset;
}

function polyfillDataset(element: HTMLElement): Dataset {
  return [].slice.call(element.attributes).reduce((data, { name, value }) => {
    if (/^data-(.+)/.test(name)) {
      const normalizedName = name
        .substr(5)
        .replace(/-\w/g, str => str[1].toUpperCase());

      data[normalizedName] = value;
    }

    return data;
  }, {});
}

function getDatasetFn(): DatasetFn {
  const element = document.createElement("div");

  return element.dataset ? nativeDataset : polyfillDataset;
}

const datasetFn: DatasetFn = getDatasetFn();

function dataset(element: HTMLElement): Dataset {
  return datasetFn(element);
}

/*
 * Traverse
 */

function parent(element: Element): ?Element {
  return element.parentElement;
}

function parentBy(
  element: Element,
  condition: PredicateFn | Selector
): ?Element {
  const predicate = typeof condition === "string"
    ? e => matches(e, condition)
    : condition;

  let current = parent(element);

  while (current) {
    if (predicate(current)) {
      return current;
    }

    current = parent(current);
  }

  return null;
}

function parents(element: Element): Elements {
  const result = [];

  let current = element.parentElement;

  while (current) {
    result.push(current);

    current = current.parentElement;
  }

  return result;
}

function parentsBy(
  element: Element,
  condition: Selector | PredicateFn
): Elements {
  const predicate = typeof condition === "string"
    ? e => matches(e, condition)
    : condition;

  return parents(element).filter(predicate);
}

/*
 * Manipulate
 */

function remove(element: Element): boolean {
  const parentElement = parent(element);

  if (parentElement) {
    parentElement.removeChild(element);

    return true;
  }

  return false;
}

/*
 * Exports
 */

export {
  /* queries */
  query,
  queryAll,
  matches,
  /* classes */
  hasClass,
  addClass,
  removeClass,
  toggleClass,
  /* dataset */
  dataset,
  /* traverse */
  parent,
  parentBy,
  parents,
  parentsBy,
  /* manipulate */
  remove
};
<commit_msg>Rewrite `parents` function<commit_after>/* @flow */

/*
 * Types
 */

type CSSClass = string;

type Elements = Array<Element>;

type PredicateFn = (element: Element) => boolean;

type Selector = string;

/*
 * Utilities
 */

function toArray(arrayLike: any): Array<any> {
  return Array.prototype.slice.call(arrayLike);
}

/*
 * Queries
 */

function query(element: Element, selector: Selector): ?Element {
  return element.querySelector(selector);
}

function queryAll(element: Element, selector: Selector): Elements {
  const elements = element.querySelectorAll(selector);

  return (toArray(elements): Elements);
}

type MatchesFn = (selector: Selector) => boolean;

function getMatchesFn(): MatchesFn {
  const element = (document.createElement("div"): any);

  return (
    element.matches ||
    element.matchesSelector ||
    element.msMatchesSelector ||
    element.mozMatchesSelector ||
    element.webkitMatchesSelector ||
    element.oMatchesSelector
  );
}

const matchesFn: MatchesFn = getMatchesFn();

function matches(element: Element, selector: Selector): boolean {
  return matchesFn.call(element, selector);
}

/*
 * Classes
 */

function hasClass(element: Element, cssClass: CSSClass): boolean {
  return element.classList.contains(cssClass);
}

function addClass(element: Element, cssClass: CSSClass): boolean {
  const result = !hasClass(element, cssClass);

  if (result) {
    element.classList.add(cssClass);
  }

  return result;
}

function removeClass(element: Element, cssClass: CSSClass): boolean {
  const result = hasClass(element, cssClass);

  if (result) {
    element.classList.remove(cssClass);
  }

  return result;
}

function toggleClass(
  element: Element,
  cssClass: CSSClass,
  state?: boolean
): boolean {
  const target = arguments.length === 3 ? state : !hasClass(element, cssClass);
  const toggleFn = target ? addClass : removeClass;

  return toggleFn(element, cssClass);
}

/*
 * Dataset
 */

type Dataset = { [key: string]: string };

type DatasetFn = (element: HTMLElement) => Dataset;

function nativeDataset(element: HTMLElement): Dataset {
  return element.dataset;
}

function polyfillDataset(element: HTMLElement): Dataset {
  return [].slice.call(element.attributes).reduce((data, { name, value }) => {
    if (/^data-(.+)/.test(name)) {
      const normalizedName = name
        .substr(5)
        .replace(/-\w/g, str => str[1].toUpperCase());

      data[normalizedName] = value;
    }

    return data;
  }, {});
}

function getDatasetFn(): DatasetFn {
  const element = document.createElement("div");

  return element.dataset ? nativeDataset : polyfillDataset;
}

const datasetFn: DatasetFn = getDatasetFn();

function dataset(element: HTMLElement): Dataset {
  return datasetFn(element);
}

/*
 * Traverse
 */

function parent(element: Element): ?Element {
  return element.parentElement;
}

function parentBy(
  element: Element,
  condition: PredicateFn | Selector
): ?Element {
  const predicate = typeof condition === "string"
    ? e => matches(e, condition)
    : condition;

  let current = parent(element);

  while (current) {
    if (predicate(current)) {
      return current;
    }

    current = parent(current);
  }

  return null;
}

function parents(element: Element): Elements {
  const result = [];

  let current = parent(element);

  while (current) {
    result.push(current);

    current = parent(current);
  }

  return result;
}

function parentsBy(
  element: Element,
  condition: Selector | PredicateFn
): Elements {
  const predicate = typeof condition === "string"
    ? e => matches(e, condition)
    : condition;

  return parents(element).filter(predicate);
}

/*
 * Manipulate
 */

function remove(element: Element): boolean {
  const parentElement = parent(element);

  if (parentElement) {
    parentElement.removeChild(element);

    return true;
  }

  return false;
}

/*
 * Exports
 */

export {
  /* queries */
  query,
  queryAll,
  matches,
  /* classes */
  hasClass,
  addClass,
  removeClass,
  toggleClass,
  /* dataset */
  dataset,
  /* traverse */
  parent,
  parentBy,
  parents,
  parentsBy,
  /* manipulate */
  remove
};
<|endoftext|>


<commit_before>import {BigNumber} from 'bignumber.js';

// http://stackoverflow.com/questions/3885817/how-to-check-if-a-number-is-float-or-integer
const isInt = (maybeInt) => maybeInt % 1 === 0;

const compareCentsFunction = (comparator, Class) =>
  function (val, options) {
    if (options == null) {
      options = {};
    }
    const cents = this;
    if (options.strict == null) {
      options.strict = true;
    }
    if (options.strict) {
      return val instanceof Class && comparator(cents, val);
    }
    const otherCents = new Class(val);
    return comparator(cents, otherCents);
  };

const comparators = {
  equals(cents, otherCents) {
    return cents.toNumber() === otherCents.toNumber();
  },
  lessThan(cents, otherCents) {
    return cents.toNumber() < otherCents.toNumber();
  },
  lessThanOrEqual(cents, otherCents) {
    return cents.toNumber() <= otherCents.toNumber();
  },
  greaterThan(cents, otherCents) {
    return cents.toNumber() > otherCents.toNumber();
  },
  greaterThanOrEqual(cents, otherCents) {
    return cents.toNumber() >= otherCents.toNumber();
  },
};

// This method supports static method calls of the form:
//   Cents.staticMethod(...)
//
// The ... must include at least one argument.
//
// Case 1: ... => single argument array
//   There must be no other arguments and each value in the array must "pass" the
//   validator (boolean) predicate function. Returns the array.
// Case 2: ... => multiple argument values
//   Each value must "pass" the validator predicate function. Returns an array of the values.
const arrayifySplat = function (splat, validator) {
  if (!(splat.length > 0)) {
    throw new Error('Expect at least one argument');
  }

  if (Array.isArray(splat[0])) {
    if (splat.length !== 1) {
      throw new Error('Expect a single array argument');
    }
    splat = splat[0];
  }

  if (validator != null) {
    splat.forEach(function (val) {
      if (!validator(val)) {
        throw new Error(`Unexpected value ${val}`);
      }
    });
  }

  return splat;
};
class Cents {
  constructor(value) {
    this.equals = compareCentsFunction(comparators.equals, Cents);
    this.lessThan = compareCentsFunction(comparators.lessThan, Cents);
    this.lessThanOrEqual = compareCentsFunction(comparators.lessThanOrEqual, Cents);
    this.greaterThan = compareCentsFunction(comparators.greaterThan, Cents);
    this.greaterThanOrEqual = compareCentsFunction(comparators.greaterThanOrEqual, Cents);
    this.value = value;
    if ((this.value != null ? this.value.toNumber : undefined) != null) {
      // Could be instanceof BigNumber or Cents.
      this.value = this.value.toNumber();
    }

    if (typeof this.value === 'string') {
      this.value = Number(this.value);
    }
    if (typeof this.value !== 'number') {
      throw new Error(`${this.value} must be a Number`);
    }
    if (isNaN(this.value)) {
      throw new Error(`${this.value} must not be NaN`);
    }
    if (!isInt(this.value)) {
      throw new Error(`${this.value} must be an int`);
    }
    if (this.value < 0) {
      throw new Error(`${this.value} must not be negative`);
    }
  }

  toBigNumber() {
    return new BigNumber(this.value);
  }
  toDollars() {
    return this.toBigNumber().dividedBy(100).toNumber();
  }
  toNumber() {
    return this.value;
  }

  plus(cents, param) {
    if (param == null) {
      param = {strict: false};
    }
    const {strict} = param;
    if (!strict) {
      cents = new Cents(cents);
    }
    return new Cents(this.toBigNumber().plus(cents.toNumber()));
  }

  minus(cents, param) {
    if (param == null) {
      param = {strict: false, maxZero: false};
    }
    const {strict, maxZero} = param;
    if (!strict) {
      cents = new Cents(cents);
    }
    const result = this.toBigNumber().minus(cents.toNumber()).toNumber(); // Number; may be negative

    if (maxZero) {
      return new Cents(Math.max(0, result));
    }
    return new Cents(result); // will throw if negative
  }

  times(scalar, param) {
    // Transform can be any no-arg BigNumber function and should produce a valid Cents value.
    // e.g. 'ceil', 'round'
    if (param == null) {
      param = {};
    }
    const {transform} = param;
    let result = this.toBigNumber().times(scalar);
    if (transform != null) {
      result = this._applyBackwardsCompatibleTransform(result, transform);
    }
    return new Cents(result);
  }

  dividedBy(scalar, param) {
    // Transform can be any no-arg BigNumber function and should produce a valid Cents value.
    // e.g. 'ceil', 'round'
    if (param == null) {
      param = {};
    }
    const {transform} = param;
    let result = this.toBigNumber().dividedBy(scalar);
    if (transform != null) {
      result = this._applyBackwardsCompatibleTransform(result, transform);
    }
    return new Cents(result);
  }

  percent(percent, param) {
    // Is equivalent to @times(percent / 100, {transform})
    // but avoids (percent / 100) returning too many sig figs for BigNumber.
    // TODO(serhalp) this is no longer an issue since BigNumber.js@7.0.0:
    // https://github.com/MikeMcl/bignumber.js/blob/master/CHANGELOG.md#700. Simplify?
    if (param == null) {
      param = {transform: 'round'};
    }
    const {transform} = param;
    const scalar = new BigNumber(percent).dividedBy(100).toNumber();
    return this.times(scalar, {transform});
  }

  // Handy aliases.
  is0() {
    return this.equals(new Cents(0));
  }
  isnt0() {
    return !this.is0();
  }

  toString() {
    return `$${new BigNumber(this.toDollars()).toFixed(2)}`;
  } // always show 2 decimal places

  // BigNumber.js removed `round()`, `ceil()`, and `floor()` in in v6.0.0. Previously this library
  // allowed magically calling through to underlying BigNumber.js methods. This is a shim to
  // continue to transparently continue to support the frequently used `round` "transform" without
  // breaking backwards compatibility.
  _applyBackwardsCompatibleTransform(bigNumber, transform) {
    if (transform === 'round') {
      return bigNumber.integerValue(BigNumber.ROUND_HALF_UP);
    } else if (transform === 'floor') {
      return bigNumber.integerValue(BigNumber.ROUND_FLOOR);
    } else if (transform === 'ceil') {
      return bigNumber.integerValue(BigNumber.ROUND_CEIL);
    } else if (typeof bigNumber[transform] !== 'function') {
      throw new TypeError(
        `Cannot apply transform '${transform}', is not a supported BigNumber.js method`,
      );
    } else {
      return bigNumber[transform]();
    }
  }

  lt(...args) {
    return Reflect.apply(this.lessThan, this, args);
  }

  lte(...args) {
    return Reflect.apply(this.lessThanOrEqual, this, args);
  }

  gt(...args) {
    return Reflect.apply(this.greaterThan, this, args);
  }

  gte(...args) {
    return Reflect.apply(this.greaterThanOrEqual, this, args);
  }

  static isValid(maybeCents) {
    let centsInstance;
    try {
      centsInstance = new Cents(maybeCents);
    } catch {
      centsInstance = new Error('invalid');
    }
    return centsInstance instanceof Cents;
  }

  static isValidDollars(maybeDollars) {
    let threw = false;
    try {
      Cents.fromDollars(maybeDollars);
    } catch {
      threw = true;
    }
    return !threw;
  }

  static fromDollars = (
    dollars, // dollars should be a Number like xx.yy
  ) => new Cents(new BigNumber(dollars).times(100));

  static round(maybeInt) {
    if (!(maybeInt >= 0)) {
      throw new Error(`${maybeInt} must be positive to round to cents`);
    }
    return new Cents(new BigNumber(maybeInt).integerValue(BigNumber.ROUND_HALF_UP));
  }

  static min(...cents) {
    cents = arrayifySplat(cents, Cents.isValid);
    cents = cents.map((cent) => new Cents(cent).toNumber());
    const min = Math.min(...cents);
    return new Cents(min);
  }

  static max(...cents) {
    cents = arrayifySplat(cents, Cents.isValid);
    cents = cents.map((cent) => new Cents(cent).toNumber());
    const max = Math.max(...cents);
    return new Cents(max);
  }

  static sum(...cents) {
    cents = arrayifySplat(cents, Cents.isValid);
    return cents.reduce((memo, val) => memo.plus(val), new Cents(0));
  }

  static sumDollars(...dollars) {
    dollars = arrayifySplat(dollars, Cents.isValidDollars);
    return dollars.reduce((memo, val) => memo.plus(Cents.fromDollars(val)), new Cents(0));
  }
}

export default Cents;
<commit_msg>cleaned cloned methods<commit_after>import {BigNumber} from 'bignumber.js';

// http://stackoverflow.com/questions/3885817/how-to-check-if-a-number-is-float-or-integer
const isInt = (maybeInt) => maybeInt % 1 === 0;

const compareCentsFunction = (comparator, Class) =>
  function (val, options) {
    if (options == null) {
      options = {};
    }
    const cents = this;
    if (options.strict == null) {
      options.strict = true;
    }
    if (options.strict) {
      return val instanceof Class && comparator(cents, val);
    }
    const otherCents = new Class(val);
    return comparator(cents, otherCents);
  };

const comparators = {
  equals(cents, otherCents) {
    return cents.toNumber() === otherCents.toNumber();
  },
  lessThan(cents, otherCents) {
    return cents.toNumber() < otherCents.toNumber();
  },
  lessThanOrEqual(cents, otherCents) {
    return cents.toNumber() <= otherCents.toNumber();
  },
  greaterThan(cents, otherCents) {
    return cents.toNumber() > otherCents.toNumber();
  },
  greaterThanOrEqual(cents, otherCents) {
    return cents.toNumber() >= otherCents.toNumber();
  },
};

// This method supports static method calls of the form:
//   Cents.staticMethod(...)
//
// The ... must include at least one argument.
//
// Case 1: ... => single argument array
//   There must be no other arguments and each value in the array must "pass" the
//   validator (boolean) predicate function. Returns the array.
// Case 2: ... => multiple argument values
//   Each value must "pass" the validator predicate function. Returns an array of the values.
const arrayifySplat = function (splat, validator) {
  if (!(splat.length > 0)) {
    throw new Error('Expect at least one argument');
  }

  if (Array.isArray(splat[0])) {
    if (splat.length !== 1) {
      throw new Error('Expect a single array argument');
    }
    splat = splat[0];
  }

  if (validator != null) {
    splat.forEach(function (val) {
      if (!validator(val)) {
        throw new Error(`Unexpected value ${val}`);
      }
    });
  }

  return splat;
};
class Cents {
  constructor(value) {
    this.equals = compareCentsFunction(comparators.equals, Cents);
    this.lessThan = compareCentsFunction(comparators.lessThan, Cents);
    this.lt = this.lessThan;
    this.lessThanOrEqual = compareCentsFunction(comparators.lessThanOrEqual, Cents);
    this.lte = this.lessThanOrEqual;
    this.greaterThan = compareCentsFunction(comparators.greaterThan, Cents);
    this.gt = this.greaterThan;
    this.greaterThanOrEqual = compareCentsFunction(comparators.greaterThanOrEqual, Cents);
    this.gte = this.greaterThanOrEqual;
    this.value = value;
    if ((this.value != null ? this.value.toNumber : undefined) != null) {
      // Could be instanceof BigNumber or Cents.
      this.value = this.value.toNumber();
    }

    if (typeof this.value === 'string') {
      this.value = Number(this.value);
    }
    if (typeof this.value !== 'number') {
      throw new Error(`${this.value} must be a Number`);
    }
    if (isNaN(this.value)) {
      throw new Error(`${this.value} must not be NaN`);
    }
    if (!isInt(this.value)) {
      throw new Error(`${this.value} must be an int`);
    }
    if (this.value < 0) {
      throw new Error(`${this.value} must not be negative`);
    }
  }

  toBigNumber() {
    return new BigNumber(this.value);
  }
  toDollars() {
    return this.toBigNumber().dividedBy(100).toNumber();
  }
  toNumber() {
    return this.value;
  }

  plus(cents, param) {
    if (param == null) {
      param = {strict: false};
    }
    const {strict} = param;
    if (!strict) {
      cents = new Cents(cents);
    }
    return new Cents(this.toBigNumber().plus(cents.toNumber()));
  }

  minus(cents, param) {
    if (param == null) {
      param = {strict: false, maxZero: false};
    }
    const {strict, maxZero} = param;
    if (!strict) {
      cents = new Cents(cents);
    }
    const result = this.toBigNumber().minus(cents.toNumber()).toNumber(); // Number; may be negative

    if (maxZero) {
      return new Cents(Math.max(0, result));
    }
    return new Cents(result); // will throw if negative
  }

  times(scalar, param) {
    // Transform can be any no-arg BigNumber function and should produce a valid Cents value.
    // e.g. 'ceil', 'round'
    if (param == null) {
      param = {};
    }
    const {transform} = param;
    let result = this.toBigNumber().times(scalar);
    if (transform != null) {
      result = this._applyBackwardsCompatibleTransform(result, transform);
    }
    return new Cents(result);
  }

  dividedBy(scalar, param) {
    // Transform can be any no-arg BigNumber function and should produce a valid Cents value.
    // e.g. 'ceil', 'round'
    if (param == null) {
      param = {};
    }
    const {transform} = param;
    let result = this.toBigNumber().dividedBy(scalar);
    if (transform != null) {
      result = this._applyBackwardsCompatibleTransform(result, transform);
    }
    return new Cents(result);
  }

  percent(percent, param) {
    // Is equivalent to @times(percent / 100, {transform})
    // but avoids (percent / 100) returning too many sig figs for BigNumber.
    // TODO(serhalp) this is no longer an issue since BigNumber.js@7.0.0:
    // https://github.com/MikeMcl/bignumber.js/blob/master/CHANGELOG.md#700. Simplify?
    if (param == null) {
      param = {transform: 'round'};
    }
    const {transform} = param;
    const scalar = new BigNumber(percent).dividedBy(100).toNumber();
    return this.times(scalar, {transform});
  }

  // Handy aliases.
  is0() {
    return this.equals(new Cents(0));
  }
  isnt0() {
    return !this.is0();
  }

  toString() {
    return `$${new BigNumber(this.toDollars()).toFixed(2)}`;
  } // always show 2 decimal places

  // BigNumber.js removed `round()`, `ceil()`, and `floor()` in in v6.0.0. Previously this library
  // allowed magically calling through to underlying BigNumber.js methods. This is a shim to
  // continue to transparently continue to support the frequently used `round` "transform" without
  // breaking backwards compatibility.
  _applyBackwardsCompatibleTransform(bigNumber, transform) {
    if (transform === 'round') {
      return bigNumber.integerValue(BigNumber.ROUND_HALF_UP);
    } else if (transform === 'floor') {
      return bigNumber.integerValue(BigNumber.ROUND_FLOOR);
    } else if (transform === 'ceil') {
      return bigNumber.integerValue(BigNumber.ROUND_CEIL);
    } else if (typeof bigNumber[transform] !== 'function') {
      throw new TypeError(
        `Cannot apply transform '${transform}', is not a supported BigNumber.js method`,
      );
    } else {
      return bigNumber[transform]();
    }
  }

  static isValid(maybeCents) {
    let centsInstance;
    try {
      centsInstance = new Cents(maybeCents);
    } catch {
      centsInstance = new Error('invalid');
    }
    return centsInstance instanceof Cents;
  }

  static isValidDollars(maybeDollars) {
    let threw = false;
    try {
      Cents.fromDollars(maybeDollars);
    } catch {
      threw = true;
    }
    return !threw;
  }

  static fromDollars = (
    dollars, // dollars should be a Number like xx.yy
  ) => new Cents(new BigNumber(dollars).times(100));

  static round(maybeInt) {
    if (!(maybeInt >= 0)) {
      throw new Error(`${maybeInt} must be positive to round to cents`);
    }
    return new Cents(new BigNumber(maybeInt).integerValue(BigNumber.ROUND_HALF_UP));
  }

  static min(...cents) {
    cents = arrayifySplat(cents, Cents.isValid);
    cents = cents.map((cent) => new Cents(cent).toNumber());
    const min = Math.min(...cents);
    return new Cents(min);
  }

  static max(...cents) {
    cents = arrayifySplat(cents, Cents.isValid);
    cents = cents.map((cent) => new Cents(cent).toNumber());
    const max = Math.max(...cents);
    return new Cents(max);
  }

  static sum(...cents) {
    cents = arrayifySplat(cents, Cents.isValid);
    return cents.reduce((memo, val) => memo.plus(val), new Cents(0));
  }

  static sumDollars(...dollars) {
    dollars = arrayifySplat(dollars, Cents.isValidDollars);
    return dollars.reduce((memo, val) => memo.plus(Cents.fromDollars(val)), new Cents(0));
  }
}

export default Cents;
<|endoftext|>


<commit_before>import React from 'react'
import {
    render
} from 'react-dom'
import {
    Router,
    Route,
    IndexRedirect,
    Redirect,
    browserHistory
} from 'react-router'
import App from './containers/App';
import Gif from './containers/Gif';
import Search from './containers/Search';
import Options from './containers/Options';
import * as GifAPI from './apis/GifAPI';
import * as GifActions from './actions/GifActions';

if(process.env.NODE_ENV === 'development') {
    GifAPI.mock(100);
}

GifActions.loadData();

// toastr setup
toastr.options.preventDuplicates = true; //eslint-disable-line no-undef
toastr.options.progressBar = true; //eslint-disable-line no-undef

const router = (
    <Router history={browserHistory}>
        <Route path="/" component={App}>
            <IndexRedirect to='/gifs' />
            <Route path="gifs" component={Gif} />
            <Route path="search" component={Search} />
            <Route path="options" component={Options} />
            <Redirect from="*" to="/gifs" />
        </Route>
    </Router>
);

render(router, document.getElementById('root'));<commit_msg>Do setup before mock<commit_after>import React from 'react'
import {
    render
} from 'react-dom'
import {
    Router,
    Route,
    IndexRedirect,
    Redirect,
    browserHistory
} from 'react-router'
import App from './containers/App';
import Gif from './containers/Gif';
import Search from './containers/Search';
import Options from './containers/Options';
import * as GifAPI from './apis/GifAPI';
import * as GifActions from './actions/GifActions';

// toastr setup
toastr.options.preventDuplicates = true; //eslint-disable-line no-undef
toastr.options.progressBar = true; //eslint-disable-line no-undef

// NProgress setup
NProgress.configure({ //eslint-disable-line no-undef
    showSpinner: false
});

if (process.env.NODE_ENV === 'development') {
    GifAPI.mock(100);
}

GifActions.loadData();

const router = (
    <Router history={browserHistory}>
        <Route path="/" component={App}>
            <IndexRedirect to='/gifs' />
            <Route path="gifs" component={Gif} />
            <Route path="search" component={Search} />
            <Route path="options" component={Options} />
            <Redirect from="*" to="/gifs" />
        </Route>
    </Router>
);

render(router, document.getElementById('root'));<|endoftext|>


<commit_before>(function(root) {

  // Set an empty reference to _
  var _;

  // UUID
  // https://gist.github.com/jed/982883
  /* jshint ignore:start */
  function b(
    a                  // placeholder
  ){
    return a           // if the placeholder was passed, return
      ? (              // a random number from 0 to 15
        a ^            // unless b is 8,
        Math.random()  // in which case
        * 16           // a random number from
        >> a/4         // 8 to 11
        ).toString(16) // in hexadecimal
      : (              // or otherwise a concatenated string:
        [1e7] +        // 10000000 +
        -1e3 +         // -1000 +
        -4e3 +         // -4000 +
        -8e3 +         // -80000000 +
        -1e11          // -100000000000,
        ).replace(     // replacing
          /[018]/g,    // zeroes, ones, and eights with
          b            // random hex digits
        )
  }
  /* jshint ignore:end */

  // Copies properties from an object to another
  function __update(dest, src) {
    _.each(src, function(value, key) {
      dest[key] = value;
    });
  }

  // Removes an item from an array
  function __remove(array, item) {
    var index = _.indexOf(array, item);
    if (index != -1) array.splice(index, 1);
  }

  function get(collection, id) {
    return _.find(collection, function (doc) {
      return doc.id === id;
    });
  }

  function createId(collection) {
    return b();
  }

  function insert(collection, obj) {
    var clone = _.clone(obj);

    if (!clone.hasOwnProperty('id')) clone.id = _.createId(collection);

    collection.push(clone);

    return clone;
  }

  function update(collection, id, attrs) {
    var doc = get(collection, id);

    if (doc) __update(doc, attrs);

    return doc;
  }

  function updateWhere(collection, whereAttrs, attrs) {
    var docs = _.where(collection, whereAttrs);

    docs.forEach(function(doc) {
      __update(doc, attrs);
    });

    return docs;
  }

  function remove(collection, id) {
    var doc = get(collection, id);

    __remove(collection, doc);

    return doc;
  }

  function removeWhere(collection, attrs) {
    var docs = _.where(collection, attrs);

    docs.forEach(function(doc) {
      __remove(collection, doc);
    });

    return docs;
  }

  function mixWith(lib) {
    _ = lib;
    _.mixin({
      get: get,
      createId: createId,
      insert: insert,
      update: update,
      updateWhere: updateWhere,
      remove: remove,
      removeWhere: removeWhere
    });
  }

  if (typeof module !== 'undefined' && module.exports) {
    module.exports.mixWith = mixWith;
  } else {
    mixWith(root._);
  }
})(this);<commit_msg>Pass doc parameter to createId<commit_after>(function(root) {

  // Set an empty reference to _
  var _;

  // UUID
  // https://gist.github.com/jed/982883
  /* jshint ignore:start */
  function b(
    a                  // placeholder
  ){
    return a           // if the placeholder was passed, return
      ? (              // a random number from 0 to 15
        a ^            // unless b is 8,
        Math.random()  // in which case
        * 16           // a random number from
        >> a/4         // 8 to 11
        ).toString(16) // in hexadecimal
      : (              // or otherwise a concatenated string:
        [1e7] +        // 10000000 +
        -1e3 +         // -1000 +
        -4e3 +         // -4000 +
        -8e3 +         // -80000000 +
        -1e11          // -100000000000,
        ).replace(     // replacing
          /[018]/g,    // zeroes, ones, and eights with
          b            // random hex digits
        )
  }
  /* jshint ignore:end */

  // Copies properties from an docect to another
  function __update(dest, src) {
    _.each(src, function(value, key) {
      dest[key] = value;
    });
  }

  // Removes an item from an array
  function __remove(array, item) {
    var index = _.indexOf(array, item);
    if (index != -1) array.splice(index, 1);
  }

  function get(collection, id) {
    return _.find(collection, function (doc) {
      return doc.id === id;
    });
  }

  function createId() {
    return b();
  }

  function insert(collection, doc) {
    var clone = _.clone(doc);

    if (!clone.hasOwnProperty('id')) clone.id = _.createId(collection, doc);

    collection.push(clone);

    return clone;
  }

  function update(collection, id, attrs) {
    var doc = get(collection, id);

    if (doc) __update(doc, attrs);

    return doc;
  }

  function updateWhere(collection, whereAttrs, attrs) {
    var docs = _.where(collection, whereAttrs);

    docs.forEach(function(doc) {
      __update(doc, attrs);
    });

    return docs;
  }

  function remove(collection, id) {
    var doc = get(collection, id);

    __remove(collection, doc);

    return doc;
  }

  function removeWhere(collection, attrs) {
    var docs = _.where(collection, attrs);

    docs.forEach(function(doc) {
      __remove(collection, doc);
    });

    return docs;
  }

  function mixWith(lib) {
    _ = lib;
    _.mixin({
      get: get,
      createId: createId,
      insert: insert,
      update: update,
      updateWhere: updateWhere,
      remove: remove,
      removeWhere: removeWhere
    });
  }

  if (typeof module !== 'undefined' && module.exports) {
    module.exports.mixWith = mixWith;
  } else {
    mixWith(root._);
  }
})(this);<|endoftext|>


<commit_before>import fs from 'fs';
import path from 'path';

import { createFilter } from 'rollup-pluginutils';

const componentRegex = /^\s*@(Component)\({([\s\S]*)}\)\s*$/gm;
const templateUrlRegex = /templateUrl\s*:(.*)/g;
const styleUrlsRegex = /styleUrls\s*:(\s*\[[\s\S]*?\])/g;
const stringRegex = /(['"])(.*?)\1/g;

function insertText(str, dir) {
  str = str.replace(stringRegex, function (match, quote, url) {
    var text = fs.readFileSync(path.join(dir, url)).toString();
    return '`' + text + '`';
  });
  return str;
}

export default function angular (options = {}) {
  var filter = createFilter(options.include, options.exclude);

  return {
    name: 'angular',
    transform(source, map) {
      if ( !filter( id ) ) return;

      var dir = path.parse(map).dir;

      source = source.replace(componentRegex, function (match, decorator, metadata) {
        metadata = metadata
          .replace(templateUrlRegex, function (match, url) {
            return 'template:' + insertText(url, dir);
          })
          .replace(styleUrlsRegex, function (match, urls) {
            return 'styles:' + insertText(urls, dir);
          });

          return '@' + decorator + '({' + metadata + '})';
      });

      return source;
    }
  };
}
<commit_msg>fix map<commit_after>import fs from 'fs';
import path from 'path';

import { createFilter } from 'rollup-pluginutils';

const componentRegex = /^\s*@(Component)\({([\s\S]*)}\)\s*$/gm;
const templateUrlRegex = /templateUrl\s*:(.*)/g;
const styleUrlsRegex = /styleUrls\s*:(\s*\[[\s\S]*?\])/g;
const stringRegex = /(['"])(.*?)\1/g;

function insertText(str, dir) {
  str = str.replace(stringRegex, function (match, quote, url) {
    var text = fs.readFileSync(path.join(dir, url)).toString();
    return '`' + text + '`';
  });
  return str;
}

export default function angular (options = {}) {
  var filter = createFilter(options.include, options.exclude);

  return {
    name: 'angular',
    transform(source, map) {
      if (!filter(map)) return;

      var dir = path.parse(map).dir;

      source = source.replace(componentRegex, function (match, decorator, metadata) {
        metadata = metadata
          .replace(templateUrlRegex, function (match, url) {
            return 'template:' + insertText(url, dir);
          })
          .replace(styleUrlsRegex, function (match, urls) {
            return 'styles:' + insertText(urls, dir);
          });

          return '@' + decorator + '({' + metadata + '})';
      });

      return source;
    }
  };
}
<|endoftext|>