<commit_before>var fs = require('fs');
var spawn = require('child_process').spawn;
var zlib = require('zlib');

var request = require('../modules/request');
var Progress = require('../modules/progress');
var tar = require('../modules/tar-fs/index');
var P = require('../modules/p-promise/p');

module.exports = function (log) {

  function Remote() {
  }

  Remote.freightCheck = function (url, project, extra) {
    var defer = P.defer();
    var checkUrl = url + 'freight/check';
    var data = {
      project: project,
      extra: extra
    };

    request({
      url: checkUrl,
      method: 'POST',
      form: data,
      json: true
    }, function (err, resp, body) {
      if (err) {
        log.error('Freight failed to connect to', url);

        defer.reject(err);
      } else {
        log.debug('Response:', body);
        defer.resolve(body);
      }
    });

    return defer.promise;
  };

  Remote.freightDownload = function (name, server, hash, downloadOpts) {
    downloadOpts = downloadOpts || {};
    var defer = P.defer();
    var bundleFile = 'freight_download_' + Date.now() + '.tar.gz';
    var bar;

    request
      .post(server + 'freight/download')
      .form({ hash: hash, name: name, options: downloadOpts })
      .on('response', function (res) {
        if (res.statusCode !== 200) {
          throw new Error('Failed to download Freight.');
        } else {
          var len = parseInt(res.headers['content-length'], 10);
          var filesize = require('../modules/file-size');
          var progressOutput = 'Downloading bundle: :bar :percent :etas ';
          progressOutput += filesize(len).human({ si: true });
          if (! log.disabled) {
            bar = new Progress(progressOutput, {
              complete: '|',
              incomplete: ' ',
              width: 20,
              total: len
            });
          }
        }

      })
      .on('data', function (data) {
        if (! log.disabled) {
          bar.tick(data.length);
        }
      })
      .on('error', function (err) {
        defer.reject(err);
      })
      .on('end', function () {
      })
      .pipe(fs.createWriteStream(bundleFile))
      .on('close', function (err) {
        if (err) {
          defer.reject(err);
        } else {
          defer.resolve(bundleFile);
        }
      });

    return defer.promise;
  };

  Remote.freightExtract = function (filePath) {
    var defer = P.defer();
    var extractStart = new Date();

    log.info('Extracting bundle...');
    log.debug('Working directory', process.cwd());

    fs.createReadStream(filePath)
      .pipe(zlib.Unzip())
      .pipe(tar.extract('.'))
      .on('error', function (err) {
        log.error('Extraction Failed');
        log.error(err);
        throw defer.reject(err);
      })
      .on('finish', function () {
        var end = Date.now();

        log.debug('Extraction complete in', (end - extractStart) / 1000, 'seconds.');
        log.debug('Removing', filePath);

        defer.resolve(filePath);
      });

    return defer.promise;
  };

  Remote.freightCleanup = function (filePath) {
    var defer = P.defer();

    fs.unlink(filePath, function (err) {
      if (err) {
        log.error('Failed to delete', filePath);
        log.error(err);
        defer.reject(err);
      } else {
        defer.resolve(filePath);
      }
    });

    return defer.promise;
  };

  Remote.freightPostExtract = function () {
    var defer = P.defer();
    // if this project extracted node_modules
    fs.exists('node_modules', function (exists) {
      if (exists) {
        var npmRebuild = spawn('npm', ['rebuild'], { cwd: process.cwd() });
        var errorOutput = null;

        log.info('Running NPM rebuild...');
        npmRebuild.stderr.on('data', function (data) {
          if (data) {
            log.debug(data.toString());
            errorOutput += data.toString();
          }
        });

        npmRebuild.stdout.on('data', function (data) {
          if (data) {
            log.debug(data.toString());
          }
        });

        npmRebuild.on('close', function (code) {
          if (code === 0) {
            defer.resolve();
          } else {
            log.error(errorOutput);
            defer.reject();
          }
        });
      } else {
        defer.resolve();
      }
    });

    return defer.promise;
  };

  Remote.freightDone = function (start) {
    var defer = P.defer();
    var end = Date.now();
    log.info('Freight is done in', (end - start) / 1000, 'seconds.');

    return defer.promise;
  };

  Remote.freightStatus = function (freight, url, wantedCreate) {
    log.info('************\n');
    if (freight.available) {
      log.info('Bundle exists for this project.');
    } else {
      log.info('Bundle does not exist for this project.');
    }

    if (freight.creating) {
      log.info('Freight Server will now generate a bundle.');
      // TODO: can or cannot monitor? block queue but allow?
      log.info('Monitor your Freight at', url + 'freights/active');
    } else {

      if (wantedCreate && ! freight.creating) {
        if (freight.available && freight.authenticated) {
          log.error('To recreate the bundle use --force.');
        } else {
          log.error('Wrong Freight Server password.');
        }

      } else {
        log.info('To create run: \n freight create -u=' + url);
      }
    }

    log.info('\n************');
    return P();
  };

  Remote.serverError = function (server) {
    log.info('************');
    log.info('Freight Server not found at', server);
    log.info('************');
    return P();
  };

  return Remote;
};
<commit_msg>Improve HTTP error handling<commit_after>var fs = require('fs');
var spawn = require('child_process').spawn;
var zlib = require('zlib');

var request = require('../modules/request');
var Progress = require('../modules/progress');
var tar = require('../modules/tar-fs/index');
var P = require('../modules/p-promise/p');

module.exports = function (log) {

  function Remote() {
  }

  Remote.freightCheck = function (url, project, extra) {
    var defer = P.defer();
    var checkUrl = url + 'freight/check';
    var data = {
      project: project,
      extra: extra
    };

    request({
      url: checkUrl,
      method: 'POST',
      form: data,
      json: true
    }, function (err, resp, body) {
      if (err) {
        log.error('Freight failed to connect to', url);
        defer.reject(err);
      } else {
        log.debug('Response status:', resp.statusCode);
        log.debug('Response body:', body);
        switch (resp.statusCode) {
          case 200:
            defer.resolve(body);
            break;
          case 413:
            defer.reject('Bundle too large to transmit. Try increasing `limit` on your Freight server.')
            break;
          default:
            defer.reject('Unexpected response: ' + resp.statusCode);
            break;
        }
      }
    });

    return defer.promise;
  };

  Remote.freightDownload = function (name, server, hash, downloadOpts) {
    downloadOpts = downloadOpts || {};
    var defer = P.defer();
    var bundleFile = 'freight_download_' + Date.now() + '.tar.gz';
    var bar;

    request
      .post(server + 'freight/download')
      .form({ hash: hash, name: name, options: downloadOpts })
      .on('response', function (res) {
        if (res.statusCode !== 200) {
          throw new Error('Failed to download Freight.');
        } else {
          var len = parseInt(res.headers['content-length'], 10);
          var filesize = require('../modules/file-size');
          var progressOutput = 'Downloading bundle: :bar :percent :etas ';
          progressOutput += filesize(len).human({ si: true });
          if (! log.disabled) {
            bar = new Progress(progressOutput, {
              complete: '|',
              incomplete: ' ',
              width: 20,
              total: len
            });
          }
        }

      })
      .on('data', function (data) {
        if (! log.disabled) {
          bar.tick(data.length);
        }
      })
      .on('error', function (err) {
        defer.reject(err);
      })
      .on('end', function () {
      })
      .pipe(fs.createWriteStream(bundleFile))
      .on('close', function (err) {
        if (err) {
          defer.reject(err);
        } else {
          defer.resolve(bundleFile);
        }
      });

    return defer.promise;
  };

  Remote.freightExtract = function (filePath) {
    var defer = P.defer();
    var extractStart = new Date();

    log.info('Extracting bundle...');
    log.debug('Working directory', process.cwd());

    fs.createReadStream(filePath)
      .pipe(zlib.Unzip())
      .pipe(tar.extract('.'))
      .on('error', function (err) {
        log.error('Extraction Failed');
        log.error(err);
        throw defer.reject(err);
      })
      .on('finish', function () {
        var end = Date.now();

        log.debug('Extraction complete in', (end - extractStart) / 1000, 'seconds.');
        log.debug('Removing', filePath);

        defer.resolve(filePath);
      });

    return defer.promise;
  };

  Remote.freightCleanup = function (filePath) {
    var defer = P.defer();

    fs.unlink(filePath, function (err) {
      if (err) {
        log.error('Failed to delete', filePath);
        log.error(err);
        defer.reject(err);
      } else {
        defer.resolve(filePath);
      }
    });

    return defer.promise;
  };

  Remote.freightPostExtract = function () {
    var defer = P.defer();
    // if this project extracted node_modules
    fs.exists('node_modules', function (exists) {
      if (exists) {
        var npmRebuild = spawn('npm', ['rebuild'], { cwd: process.cwd() });
        var errorOutput = null;

        log.info('Running NPM rebuild...');
        npmRebuild.stderr.on('data', function (data) {
          if (data) {
            log.debug(data.toString());
            errorOutput += data.toString();
          }
        });

        npmRebuild.stdout.on('data', function (data) {
          if (data) {
            log.debug(data.toString());
          }
        });

        npmRebuild.on('close', function (code) {
          if (code === 0) {
            defer.resolve();
          } else {
            log.error(errorOutput);
            defer.reject();
          }
        });
      } else {
        defer.resolve();
      }
    });

    return defer.promise;
  };

  Remote.freightDone = function (start) {
    var defer = P.defer();
    var end = Date.now();
    log.info('Freight is done in', (end - start) / 1000, 'seconds.');

    return defer.promise;
  };

  Remote.freightStatus = function (freight, url, wantedCreate) {
    log.info('************\n');
    if (freight.available) {
      log.info('Bundle exists for this project.');
    } else {
      log.info('Bundle does not exist for this project.');
    }

    if (freight.creating) {
      log.info('Freight Server will now generate a bundle.');
      // TODO: can or cannot monitor? block queue but allow?
      log.info('Monitor your Freight at', url + 'freights/active');
    } else {

      if (wantedCreate && ! freight.creating) {
        if (freight.available && freight.authenticated) {
          log.error('To recreate the bundle use --force.');
        } else {
          log.error('Wrong Freight Server password.');
        }

      } else {
        log.info('To create run: \n freight create -u=' + url);
      }
    }

    log.info('\n************');
    return P();
  };

  Remote.serverError = function (server) {
    log.info('************');
    log.info('Freight Server not found at', server);
    log.info('************');
    return P();
  };

  return Remote;
};
<|endoftext|>


<commit_before>'use strict';

/* render.js
 * Render CSS from a tree.
 */

const Rule = require('./rule'),
      Property = require('./property'),
      Value = require('./value');

let render = module.exports = function(tree, opts){
  opts = (typeof opts === 'object') ? opts : {};

  if (tree instanceof Rule) return render.rule(tree, opts);
  if (tree instanceof Property) return render.property(tree, opts);
  if (tree instanceof Value) return render.value(tree, opts);
};

render.value = function(value, opts){
  // Numeric value
  if (value.has('numeric')) return value.val + (value.name || '');

  // Keyword value
  else if (value.has('keyword')) return value.val;

  // Function
  else if (value.has('function')) {
    let args = '';
    value.val.forEach((arg, i) => {
      if (typeof arg === 'number') arg = new Value(arg);
      if (!opts.weak && !(arg instanceof Value) && !arg.has('function'))
        throw new Error('functions may only contain non-function values');

      args += render(arg, opts) + (i !== value.val.length-1 ? ', ' : '');
    });

    return value.name + '(' + args + ')';
  }

  // Unknown
  else {
    if (!opts.weak)
      throw new Error('encountered unknown value when rendering.');
    else
      return '';
  }
};

render.property = function(prop, opts){
  let vals = '';
  prop.items.forEach((val, i) => {
    if (!opts.weak && !(val instanceof Value))
      throw new Error('properties may only contain Value objects');

    vals += render(val, opts) + (i !== prop.items.length-1 ? ' ' : '');
  });

  return prop.name + ':' + vals;
};

render.rule = function(rule, opts){
  // Regular @-rule
  if (rule.has('at-rule') && rule.has('non-conditional')) {
    let vals = '';
    rule.items.forEach((val, i) => {
      if (!opts.weak && !(val instanceof Value))
        throw new Error('non-conditional @-rules may only contain Values');

      vals += render(val, opts) + (i !== rule.items.length-1 ? ' ' : '');
    });

    return rule.name + ' ' + vals;
  }

  // Conditional @-rule
  else if (rule.has('at-rule') && rule.has('conditional')) {
    let sels = '';
    rule.items.forEach((sel, i) => {
      if (!opts.weak && !(sel instanceof Rule) && !sel.has('selector'))
        throw new Error('conditional @-rules may only contain selector Properties');

      sels += render(sel, opts) + (i !== rule.items.length-1 ? ' ' : '');
    });

    return rule.name + ' {' + sels + '}';
  }

  // Selector
  else if (rule.has('selector')) {
    let props = '';
    rule.items.forEach((prop, i) => {
      if (!opts.weak && !(prop instanceof Property))
        throw new Error('selector Rules may only contain Properties');

      props += render(prop, opts) + (i !== rule.items.length-1 ? '; ' : '');
    });

    return rule.name + ' {' + props + '}';
  }

  // Unknown
  else {
    if (!opts.weak)
      throw new Error('encountered unknown value when rendering.');
    else
      return '';
  }
};
<commit_msg>Fix conditional at-rule not rendering the condition<commit_after>'use strict';

/* render.js
 * Render CSS from a tree.
 */

const Rule = require('./rule'),
      Property = require('./property'),
      Value = require('./value');

let render = module.exports = function(tree, opts){
  opts = (typeof opts === 'object') ? opts : {};

  if (tree instanceof Rule) return render.rule(tree, opts);
  if (tree instanceof Property) return render.property(tree, opts);
  if (tree instanceof Value) return render.value(tree, opts);
};

render.value = function(value, opts){
  // Numeric value
  if (value.has('numeric')) return value.val + (value.name || '');

  // Keyword value
  else if (value.has('keyword')) return value.val;

  // Function
  else if (value.has('function')) {
    let args = '';
    value.val.forEach((arg, i) => {
      if (typeof arg === 'number') arg = new Value(arg);
      if (!opts.weak && !(arg instanceof Value) && !arg.has('function'))
        throw new Error('functions may only contain non-function values');

      args += render(arg, opts) + (i !== value.val.length-1 ? ', ' : '');
    });

    return value.name + '(' + args + ')';
  }

  // Unknown
  else {
    if (!opts.weak)
      throw new Error('encountered unknown value when rendering.');
    else
      return '';
  }
};

render.property = function(prop, opts){
  let vals = '';
  prop.items.forEach((val, i) => {
    if (!opts.weak && !(val instanceof Value))
      throw new Error('properties may only contain Value objects');

    vals += render(val, opts) + (i !== prop.items.length-1 ? ' ' : '');
  });

  return prop.name + ':' + vals;
};

render.rule = function(rule, opts){
  // Regular @-rule
  if (rule.has('at-rule') && rule.has('non-conditional')) {
    let vals = '';
    rule.items.forEach((val, i) => {
      if (!opts.weak && !(val instanceof Value))
        throw new Error('non-conditional @-rules may only contain Values');

      vals += render(val, opts) + (i !== rule.items.length-1 ? ' ' : '');
    });

    return rule.name + ' ' + vals;
  }

  // Conditional @-rule
  else if (rule.has('at-rule') && rule.has('conditional')) {
    let sels = '';
    rule.items.forEach((sel, i) => {
      if (!opts.weak && !(sel instanceof Rule) && !sel.has('selector'))
        throw new Error('conditional @-rules may only contain selector Properties');

      sels += render(sel, opts) + (i !== rule.items.length-1 ? ' ' : '');
    });

    let cond = '';
    if (rule.has('conditional')) {
      rule.condition.forEach((prop, i) => {
        if (typeof prop === 'string') prop = new Value(prop);
        if (!opts.weak && !(prop instanceof Property || prop instanceof Value))
          throw new Error('a conditional at-rule may only contain properties and values');

        cond += prop instanceof Property ? '(' + render(prop, opts) + ')' : render(prop, opts);
        cond += (i !== rule.condition.length-1 ? ' ' : '');
      });
    }

    return rule.name + ' ' + cond + ' {' + sels + '}';
  }

  // Selector
  else if (rule.has('selector')) {
    let props = '';
    rule.items.forEach((prop, i) => {
      if (!opts.weak && !(prop instanceof Property))
        throw new Error('selector Rules may only contain Properties');

      props += render(prop, opts) + (i !== rule.items.length-1 ? '; ' : '');
    });

    return rule.name + ' {' + props + '}';
  }

  // Unknown
  else {
    if (!opts.weak)
      throw new Error('encountered unknown value when rendering.');
    else
      return '';
  }
};
<|endoftext|>


<commit_before>var _        = require('lodash');
var fs       = require('fs-extra');
var path     = require('path');
var options  = require('./options');

//
// For now we assume synchronous rendering
//

var anyErrors = false;

exports.toDisk = function(model) {

  var opts = options.get();
  _.forEach(opts.lint, function(options, name){
    lint(name, options, model);
  })

  if(anyErrors){
    process.exit(1)
  }
  if (opts.overwrite) {
    var newModel = [];
    var list = require(process.cwd() + opts.overwrite).list;
    list.forEach(function(doc) {
      for(var index = 0; index < model.length; index++) {
        if(model[index].name == doc.name && model[index].hierarchy[0] == doc.describe) {
          model[index].name = doc.newName;
          model[index].hierarchy[1] = doc.newName;
          model[index].summary = doc.newSummary;
          newModel.push(model[index])
        }
      }
    });
    model = newModel;
  }
  _.forEach(opts.renderers, function(options, name) {
    render(name, options, model);
  });
  console.log('\nDone!\n');
};

function lint(name, options, model){
  var instance = null;
  try {
    instance = require('./linters/' + name);
  } catch(ex) {
    console.error('Unsupported linter: ' + name);
    return;
  }
  console.log('\n-> Linting ' + name);
  var errors = instance.lint(model, options).errors

  if(errors.length){
    var message = name + " found invalid samples: " + errors.join(", ");
    switch(options){
    case 1:
        console.warn('WARNING: ' + message)
        break;
      case 2:
        anyErrors = true;
        console.error('ERROR: ' + message)
        break;
    }
  }
}

function render(name, options, model) {
  var instance = null;
  try {
    instance = require('./renderers/' + name + '/index');
  } catch(ex) {
    console.error('Unsupported renderer: ' + name);
    return;
  }
  console.log('\n-> Building ' + name);
  instance.render(model, options);
}
<commit_msg>Pick all tests in case of overwrite<commit_after>var _        = require('lodash');
var fs       = require('fs-extra');
var path     = require('path');
var options  = require('./options');

//
// For now we assume synchronous rendering
//

var anyErrors = false;

exports.toDisk = function(model) {

  var opts = options.get();
  _.forEach(opts.lint, function(options, name){
    lint(name, options, model);
  })

  if(anyErrors){
    process.exit(1)
  }
  if (opts.overwrite) {
    var list = require(process.cwd() + opts.overwrite).list;
    list.forEach(function(doc) {
      for(var index = 0; index < model.length; index++) {
        if(model[index].name == doc.name && model[index].hierarchy[0] == doc.describe) {
          model[index].name = doc.newName;
          model[index].hierarchy[1] = doc.newName;
          model[index].summary = doc.newSummary;
        }
      }
    });
  }
  _.forEach(opts.renderers, function(options, name) {
    render(name, options, model);
  });
  console.log('\nDone!\n');
};

function lint(name, options, model){
  var instance = null;
  try {
    instance = require('./linters/' + name);
  } catch(ex) {
    console.error('Unsupported linter: ' + name);
    return;
  }
  console.log('\n-> Linting ' + name);
  var errors = instance.lint(model, options).errors

  if(errors.length){
    var message = name + " found invalid samples: " + errors.join(", ");
    switch(options){
    case 1:
        console.warn('WARNING: ' + message)
        break;
      case 2:
        anyErrors = true;
        console.error('ERROR: ' + message)
        break;
    }
  }
}

function render(name, options, model) {
  var instance = null;
  try {
    instance = require('./renderers/' + name + '/index');
  } catch(ex) {
    console.error('Unsupported renderer: ' + name);
    return;
  }
  console.log('\n-> Building ' + name);
  instance.render(model, options);
}
<|endoftext|>


<commit_before>/*globals document*/

'use strict';

var page = require('page');
var React = require('react');
var app = {};
var __slice = [].slice;

var renderView = function(opt, cb) {
  if (opt == null) {
    opt = {};
  }
  if (typeof opt.view === 'function') {
    opt.view = opt.view(opt.args);
    return renderView(opt, cb);
  } else {
    React.renderComponent(opt.view, opt.el);
    return cb();
  }
};

app.createRouteHandler = function(opt) {
  if (typeof opt === 'string') {
    return function(ctx, next) {
      return require([opt], function(fn) {
        return fn(ctx, next);
      });
    };
  } else {
    return app.createRenderHandler(opt);
  }
};

app.createRenderHandler = function(opt) {

  if (opt == null) {
    opt = {};
  }
  if (opt['continue'] == null) {
    opt['continue'] = true;
  }
  if (typeof opt.el === 'string') {
    opt.el = document.getElementById(opt.el);
  }
  var handler = function(ctx, next) {
    var nopt;
    nopt = {
      el: opt.el,
      view: opt.view,
      args: ctx
    };
    return renderView(nopt, function() {
      if (opt.title != null) {
        document.title = opt.title;
      }
      if (opt['continue']) {
        return next();
      }
    });
  };
  return handler;
};

app.route = function() {

  var route = arguments[0];
  var handlers = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  handlers = handlers.map(app.createRouteHandler);
  page.apply(null, [route].concat(__slice.call(handlers)));
  return app;
};

app.router = page;
app.use = app.route.bind(null, '*');
app.start = page.start;

module.exports = app;
<commit_msg>set continue:false by default - closes #46<commit_after>/*globals document*/

'use strict';

var page = require('page');
var React = require('react');
var app = {};
var __slice = [].slice;

var renderView = function(opt, cb) {
  if (opt == null) {
    opt = {};
  }
  if (typeof opt.view === 'function') {
    opt.view = opt.view(opt.args);
    return renderView(opt, cb);
  } else {
    React.renderComponent(opt.view, opt.el);
    return cb();
  }
};

app.createRouteHandler = function(opt) {
  if (typeof opt === 'string') {
    return function(ctx, next) {
      return require([opt], function(fn) {
        return fn(ctx, next);
      });
    };
  } else {
    return app.createRenderHandler(opt);
  }
};

app.createRenderHandler = function(opt) {

  if (opt == null) {
    opt = {};
  }
  if (opt['continue'] == null) {
    opt['continue'] = false;
  }
  if (typeof opt.el === 'string') {
    opt.el = document.getElementById(opt.el);
  }
  var handler = function(ctx, next) {
    var nopt;
    nopt = {
      el: opt.el,
      view: opt.view,
      args: ctx
    };
    return renderView(nopt, function() {
      if (opt.title != null) {
        document.title = opt.title;
      }
      if (opt['continue']) {
        return next();
      }
    });
  };
  return handler;
};

app.route = function() {

  var route = arguments[0];
  var handlers = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  handlers = handlers.map(app.createRouteHandler);
  page.apply(null, [route].concat(__slice.call(handlers)));
  return app;
};

app.router = page;
app.use = app.route.bind(null, '*');
app.start = page.start;

module.exports = app;
<|endoftext|>


<commit_before>Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
  waitOn: function(){ return Meteor.subscribe('notifications'); }
});

Router.route('/posts/:_id', {
  name: 'postPage',
  waitOn: function(){ return Meteor.subscribe('comments', this.params._id); },
  data: function(){ return Posts.findOne(this.params._id); }
});

Router.route('posts/:_id/edit', {
  name: 'postEdit',
  data: function(){ return Posts.findOne(this.params._id); }
});

Router.route('/submit', { name: 'postSubmit' });

Router.route('/:postsLimit?', {
  name: 'postsList',
  waitOn: function(){
    var limit = parseInt(this.params.postsLimit) || 5;
    return Meteor.subscribe('posts', {sort: {submitted: -1}, limit: limit});
  },
  data: function(){
    var limit = parseInt(this.params.postsLimit) || 5;
    return {
      posts: Posts.find({}, {sort: {submitted: -1}, limit: limit})
    };
  }
});

var requireLogin = function(){
  if (!Meteor.user()) {
    if (Meteor.loggingIn()) {
      this.render(this.loadingTemplate);
    } else {
      this.render('accessDenied');
    }
  } else {
    this.next();
  }
};

Router.onBeforeAction('dataNotFound', { only: 'postPage' });
Router.onBeforeAction(requireLogin, { only: 'postSubmit' });
<commit_msg>(feat) Refactors postsLists route into a RouteController<commit_after>Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
  waitOn: function(){ return Meteor.subscribe('notifications'); }
});

Router.route('/posts/:_id', {
  name: 'postPage',
  waitOn: function(){ return Meteor.subscribe('comments', this.params._id); },
  data: function(){ return Posts.findOne(this.params._id); }
});

Router.route('posts/:_id/edit', {
  name: 'postEdit',
  data: function(){ return Posts.findOne(this.params._id); }
});

Router.route('/submit', { name: 'postSubmit' });

PostsListController = RouteController.extend({
  template: 'postsList',
  increment: 5,
  postsLimit: function(){
    return parseInt(this.params.postsLimit) || this.increment;
  },
  findOptions: function(){
    return {sort: {submitted: -1}, limit: this.postsLimit()};
  },
  waitOn: function(){
    return Meteor.subscribe('posts', this.findOptions());
  },
  data: function(){
    return {posts: Posts.find({}, this.findOptions())};
  }
});

Router.route('/:postsLimit?', {
  name: 'postsList'
});

var requireLogin = function(){
  if (!Meteor.user()) {
    if (Meteor.loggingIn()) {
      this.render(this.loadingTemplate);
    } else {
      this.render('accessDenied');
    }
  } else {
    this.next();
  }
};

Router.onBeforeAction('dataNotFound', { only: 'postPage' });
Router.onBeforeAction(requireLogin, { only: 'postSubmit' });
<|endoftext|>


<commit_before>/**
 * Copyright 2014 Skytap Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

var path        = require('path'),
    fs          = require('fs'),
    extend      = require('extend'),
    q           = require('q'),
    backhoe     = require('backhoe'),
    humanize    = require('humanize-plus'),
    inflected   = require('inflected'),
    Path        = require('./path'),
    Filesystem  = require('./filesystem'),
    Logger      = require('./logger'),
    Filter      = require('./filter'),
    Environment = require('./environment'),
    Config      = require('./config'),
    Indentifier = require('./identifier');

/**
 * Module for loading controllers and wiring up routes.
 **/
var Router = {

    requestCount : 0,

    //////////////////////////////////////////////////////////////////////////
    // Public methods ///////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////

    /**
     * Router.load(app, controllerPath) -> Object
     * - app (Object): Express instance.
     * - controllerPath (String): Directory containing controllers.
     *
     * Discovers and loads all controllers.
     **/
    load : function (app, controllerPath) {
        var self = this;

        return Filesystem.recurseDirectory(controllerPath, this._filterControllers)
            .then(function loadAllControllers (files) {
                return self._loadAllControllers(app, controllerPath, files);
            })
            .then(function registerErrorController () {
                self._registerErrorController(app, controllerPath);
            });
    },

    //////////////////////////////////////////////////////////////////////////
    // Psuedo-private methods ///////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////

    /**
     * Router._buildRoutes(app) -> Null
     * - app (Object): Express app object
     **/
    _buildRoutes : function (app, controller, url) {
        var self = this,
            routes;

        url    = this._fixUrl(url);
        routes = this._getRoutesForUrl(url);

        routes.forEach(function registerRoute (route) {
            self._registerRoute(app, controller, url, route);
        });
    },

    /**
     * Router._filterControllers(file) -> Boolean
     * - file (String): controller pathname
     **/
    _filterControllers : function (file) {
        var controller = file.replace(path.extname(file), '')             // remove file extension
                .split('').reverse().join(''),                            // reverse string
            search     = 'controller/error'.split('').reverse().join(''); // reverse string

        if (controller.lastIndexOf(search) === 0) {
            return false;
        }

        var controllerPath = new Path(file);
        return controllerPath.isJavascriptFile() || controllerPath.isCoffeescriptFile();
    },

    /**
     * Router._fixUrl(url) -> String
     * - url (String)
     **/
    _fixUrl : function(url) {
        // remove filename
        url = url.replace(/index\.(js|coffee)/, '')
            .replace(/\.(js|coffee)/, '');

        // remove trailing slash
        if (url.lastIndexOf('/') === url.length - 1) {
            url = url.slice(0, url.length - 1);
        }

        // make sure URL starts with a slash
        if (url[0] !== '/') {
            url = '/' + url;
        }

        return url.replace(/\/\//g, '/');
    },

    /**
     * Router._getControllerName(parts) -> String
     * - parts (Array)
     **/
    _getControllerName : function (parts) {
        return parts
            .map(function (value) {
                return humanize.capitalize(value);
            })
            .join('');
    },

    /**
     * Router._getPage(request) -> String
     * - request (String)
     **/
    _getPage : function (request) {
        return request.url
            .split('?')[0]       // remove query string
            .replace(/^\//, '')  // remove leading slashes
            .replace(/\/$/, ''); // remove trailing slashes
    },

    /**
     * Router._getParentPathsForUrl(url) -> Array
     * - url (String)
     **/
    _getParentPathsForUrl : function (urlParts) {
        var resource = urlParts.shift();

        if (urlParts.length === 0) {
            return [ resource ];
        }

        var paths      = [
                resource,
                resource + '/:' + this._getResourceIdName(resource)
            ],
            childPaths = this._getParentPathsForUrl(urlParts),
            results    = [];

        paths.forEach(function (parentPath) {
            childPaths.forEach(function (childPath) {
                results.push(parentPath + '/' + childPath);
            });
        })

        return results;
    },

    /**
     * Router._getRoutesForUrl(url) -> Array
     * - url (String)
     **/
    _getRoutesForUrl : function (url) {
        var self     = this,
            urlParts = url.split('/')
                .filter(function ignoreEmptyString (value) {
                    return value.length > 0;
                }),
            paths    = this._getParentPathsForUrl(urlParts)
                .map(function addLeadingSlash (value) {
                    return '/' + (value ? value : '');
                }),
            routes   = [];

        paths.forEach(function addRoutes (basePath) {
            routes = routes.concat(self._getRouteTable(basePath));
        });

        return routes;
    },

    /**
     * Router._getRouteTable(url) -> Array
     * - url (String)
     *
     * Add routes for all REST methods.
     * Inspired by http://guides.rubyonrails.org/routing.html
     **/
    _getRouteTable : function (url) {
        var resourceIdName = this._getResourceIdName(url);

        return [
            {
                // GET /resource
                method  : 'get',
                url     : url,
                handler : 'index'
            },
            {
                // GET /resource/new
                method  : 'get',
                url     : this._fixUrl(url + '/new'),
                handler : 'new'
            },
            {
                // POST /resource
                method  : 'post',
                url     : url,
                handler : 'create'
            },
            {
                // GET /resource/:resourceId
                method  : 'get',
                url     : this._fixUrl(url + '/:' + resourceIdName),
                handler : 'show'
            },
            {
                // GET /resource/:resourceId/edit
                method  : 'get',
                url     : this._fixUrl(url + '/:' + resourceIdName + '/edit'),
                handler : 'edit'
            },
            {
                // PUT /resource/:resourceId
                method  : 'put',
                url     : this._fixUrl(url + '/:' + resourceIdName),
                handler : 'update'
            },
            {
                // DELETE /resource/:resourceId
                method  : 'delete',
                url     : this._fixUrl(url + '/:' + resourceIdName),
                handler : 'destroy'
            }
        ];
    },

    /**
     * Router._getResourceName(url) -> String
     * - url (String)
     **/
    _getResourceName : function (url) {
        var parts    = url.split('/'),
            resource = parts.pop();
        return inflected.singularize(resource);
    },

    /**
     * Router._getResourceIdName(url) -> String
     * - url (String)
     **/
    _getResourceIdName : function (url) {
        if (url === '/') {
            return 'id';
        }
        var resourceName = this._getResourceName(url);
        return resourceName + 'Id';
    },

    /**
     * Router._handleRequest(url, route, controller, request, response, next)
     * - url (String)
     * - route (Object)
     * - controller (Object)
     * - request (Object): Express request object.
     * - response (Object): Express response object.
     * - next (Object): Express next object.
     **/
    _handleRequest : function (url, route, controller, request, response, next) {
        var self            = this,
            filters         = controller.getFilters(url, route.handler),
            startTime       = Date.now(),
            page            = this._getPage(request),
            controllerParts = this._parseControllerName(page),
            controllerName  = this._getControllerName(controllerParts);

        request.minorjs = {
            page         : page,
            controller   : {
              name   : controllerName,
              action : route.handler,
              parts  : controllerParts
            },
            start        : startTime,
            requestToken : Indentifier.generate()
        };

        Logger.info(request, 'Request for ' + controllerName + '#' + route.handler);

        Filter.run(filters, request, response, next)
            .then(function runController (success) {
                // call the handler and return any promises
                return self._runController(controller, route, startTime, request, response, next);
            })
            .fail(function handleError (error) {
                controller._handleError(request, response, error);
            })
            .done();
    },

    /**
     * Router._handleDevelopmentRequest(controller, url, route) -> Object
     * - controller (Object)
     * - url (String)
     * - route (Object)
     **/
    _handleDevelopmentRequest : function (controller, url, route) {
        backhoe.clearCache();

        var controllerPath = controller.path,
            Controller     = require(controllerPath),
            newController  = new Controller();

        newController.path = controllerPath;
        newController.addFiltersForHandler(url, route.handler);

        return newController;
    },

    /**
     * Router._incrementRequestCount()
     **/
    _incrementRequestCount : function () {
        this.requestCount++;

        if (this._shouldStopWorker()) {
            process.emit('message', 'shutdown');
        }
    },

    /**
     * Router._loadAllControllers(app, controllerPath, files) -> Object
     * - app (Object): Express instance.
     * - controllerPath (String): Directory containing controllers.
     * - files (Array): All controllers.
     *
     * Loads all controllers.
     **/
    _loadAllControllers : function (app, controllerPath, files) {
        var self        = this,
            controllers = [];

        files.forEach(function requireController (file) {
            controllers.push(
                self._loadController(app, controllerPath, file)
            );
        });

        return q.all(controllers);
    },

    /**
     * Router._loadController(app, controllerPath, file) -> Object
     * - app (Object): Express instance.
     * - controllerPath (String): controller directory
     * - file (String): controller pathname
     **/
    _loadController : function (app, controllerPath, file) {
        var start      = Date.now(),
            fullPath   = controllerPath + '/' + file.replace(/\.(js|coffee)/, ''),
            controller = this._requireController(fullPath);

        if (!controller) {
            return;
        }

        this._buildRoutes(app, controller, file);

        Logger.profile('Load controller ' + file, start);
    },

    /**
     * Router._parseControllerName(page) -> Array
     * - page (String)
     **/
    _parseControllerName : function (page) {
        var exclude = [ 'new', 'edit' ];

        return page
            .split('/')
            .filter(function (value) {
                // ignore IDs and new/edit
                return value.length > 0 &&
                  value.length !== 32 &&
                  isNaN(parseInt(value)) &&
                  exclude.indexOf(value) === -1;
            });
    },

    /**
     * Router._registerErrorController(app, controllerPath) -> Promise
     * - app (Object): Express app object.
     * - controllerPath (String)
     **/
    _registerErrorController : function (app, controllerPath) {
        var errorControllerPath = path.join(controllerPath, 'error');

        if (!fs.existsSync(errorControllerPath + '.js') && !fs.existsSync(errorControllerPath + '.coffee')) {
            // can't find error controller. will fall back on default Express.js
            // 404 behavior.
            return;
        }

        var controller = this._requireController(errorControllerPath),
            route      = {
                method  : 'get',
                url     : /^(.*)$/,
                handler : 'index'
            },
            url        = '/error';

        this._registerRoute(app, controller, url, route);
    },

    /**
     * Router._registerRoute(app, controller, url, route)
     * - app (Object): Express app object.
     * - controller (Object): Controller instance.
     * - url (String)
     * - route (Object): Route hash
     **/
    _registerRoute : function (app, controller, url, route) {
        var self = this;

        controller.addFiltersForHandler(url, route.handler);

        app[route.method](route.url, function (request, response, next) {
            Logger.debug(
                request,
                request.method + ' ' + request.url + ' START. ' +
                'PARAMS: ' + JSON.stringify(request.params) + ', ' +
                'BODY: ' + JSON.stringify(request.body) + ', ' +
                'QUERY: ' + JSON.stringify(request.query)
            );

            if (Environment.isDevelopment()) {
                controller = self._handleDevelopmentRequest(controller, url, route);
            }

            self._incrementRequestCount();

            self._handleRequest(url, route, controller, request, response, next);
        });
    },

    /**
     * Router._requestFinished(controller, request, startTime)
     * - controller (Object): Controller instance.
     * - request (Object): Request object.
     * - startTime (Integer): Start time in milliseconds.
     **/
    _requestFinished : function (controller, request, startTime) {
        var results = extend(
            {
                method : request.method,
                time   : Date.now() - startTime
            },
            request.minorjs
        );
        controller.emit('request-finished', results);
    },

    /**
     * Router._requireController(controllerPath) -> Object
     * - controllerPath (String): controller module
     **/
    _requireController : function (controllerPath) {
        var Controller,
            controller;

        try {
            Controller = require(controllerPath);
        } catch (error) {
            Logger.error(null, "Error while loading controller '" + controllerPath + "': " + error);

            if (Environment.isWorker()) {
                process.emit('message', 'shutdown');
            } else {
                process.exit();
            }

            return;
        }

        controller      = new Controller();
        controller.path = controllerPath;

        return controller;
    },

    /**
     * Router._runController(controller, route, startTime, request, response, next) -> Object
     * - controller (Object): Controller instance.
     * - route (Object): Route hash.
     * - startTime (Integer): Start time in milliseconds.
     * - request (Object): Express request object.
     * - response (Object): Express response object.
     * - next (Object): Express next object.
     **/
    _runController : function (controller, route, startTime, request, response, next) {
        var promise = controller[route.handler]
            .call(controller, request, response, next);

        if (q.isPromise(promise)) {
            result = promise.then(this._requestFinished(controller, request, startTime));
        } else {
            this._requestFinished(controller, request, startTime);
            result = promise;
        }

        return result;
    },

    /**
     * Router._shouldStopWorker() -> Boolean
     *
     * Return true if we're a worker and we've reached the request limit.
     **/
    _shouldStopWorker : function () {
        var maxRequests;

        try {
            maxRequests = Config.get('max_requests');
        } catch (e) {
            maxRequests = 0;
        }

        return Environment.isWorker() && maxRequests > 0 && this.requestCount >= maxRequests;
    }
};

module.exports = Router;<commit_msg>Include a stack trace in the error message when loading a controller fails.<commit_after>/**
 * Copyright 2014 Skytap Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

var path        = require('path'),
    fs          = require('fs'),
    extend      = require('extend'),
    q           = require('q'),
    backhoe     = require('backhoe'),
    humanize    = require('humanize-plus'),
    inflected   = require('inflected'),
    Path        = require('./path'),
    Filesystem  = require('./filesystem'),
    Logger      = require('./logger'),
    Filter      = require('./filter'),
    Environment = require('./environment'),
    Config      = require('./config'),
    Indentifier = require('./identifier');

/**
 * Module for loading controllers and wiring up routes.
 **/
var Router = {

    requestCount : 0,

    //////////////////////////////////////////////////////////////////////////
    // Public methods ///////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////

    /**
     * Router.load(app, controllerPath) -> Object
     * - app (Object): Express instance.
     * - controllerPath (String): Directory containing controllers.
     *
     * Discovers and loads all controllers.
     **/
    load : function (app, controllerPath) {
        var self = this;

        return Filesystem.recurseDirectory(controllerPath, this._filterControllers)
            .then(function loadAllControllers (files) {
                return self._loadAllControllers(app, controllerPath, files);
            })
            .then(function registerErrorController () {
                self._registerErrorController(app, controllerPath);
            });
    },

    //////////////////////////////////////////////////////////////////////////
    // Psuedo-private methods ///////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////

    /**
     * Router._buildRoutes(app) -> Null
     * - app (Object): Express app object
     **/
    _buildRoutes : function (app, controller, url) {
        var self = this,
            routes;

        url    = this._fixUrl(url);
        routes = this._getRoutesForUrl(url);

        routes.forEach(function registerRoute (route) {
            self._registerRoute(app, controller, url, route);
        });
    },

    /**
     * Router._filterControllers(file) -> Boolean
     * - file (String): controller pathname
     **/
    _filterControllers : function (file) {
        var controller = file.replace(path.extname(file), '')             // remove file extension
                .split('').reverse().join(''),                            // reverse string
            search     = 'controller/error'.split('').reverse().join(''); // reverse string

        if (controller.lastIndexOf(search) === 0) {
            return false;
        }

        var controllerPath = new Path(file);
        return controllerPath.isJavascriptFile() || controllerPath.isCoffeescriptFile();
    },

    /**
     * Router._fixUrl(url) -> String
     * - url (String)
     **/
    _fixUrl : function(url) {
        // remove filename
        url = url.replace(/index\.(js|coffee)/, '')
            .replace(/\.(js|coffee)/, '');

        // remove trailing slash
        if (url.lastIndexOf('/') === url.length - 1) {
            url = url.slice(0, url.length - 1);
        }

        // make sure URL starts with a slash
        if (url[0] !== '/') {
            url = '/' + url;
        }

        return url.replace(/\/\//g, '/');
    },

    /**
     * Router._getControllerName(parts) -> String
     * - parts (Array)
     **/
    _getControllerName : function (parts) {
        return parts
            .map(function (value) {
                return humanize.capitalize(value);
            })
            .join('');
    },

    /**
     * Router._getPage(request) -> String
     * - request (String)
     **/
    _getPage : function (request) {
        return request.url
            .split('?')[0]       // remove query string
            .replace(/^\//, '')  // remove leading slashes
            .replace(/\/$/, ''); // remove trailing slashes
    },

    /**
     * Router._getParentPathsForUrl(url) -> Array
     * - url (String)
     **/
    _getParentPathsForUrl : function (urlParts) {
        var resource = urlParts.shift();

        if (urlParts.length === 0) {
            return [ resource ];
        }

        var paths      = [
                resource,
                resource + '/:' + this._getResourceIdName(resource)
            ],
            childPaths = this._getParentPathsForUrl(urlParts),
            results    = [];

        paths.forEach(function (parentPath) {
            childPaths.forEach(function (childPath) {
                results.push(parentPath + '/' + childPath);
            });
        })

        return results;
    },

    /**
     * Router._getRoutesForUrl(url) -> Array
     * - url (String)
     **/
    _getRoutesForUrl : function (url) {
        var self     = this,
            urlParts = url.split('/')
                .filter(function ignoreEmptyString (value) {
                    return value.length > 0;
                }),
            paths    = this._getParentPathsForUrl(urlParts)
                .map(function addLeadingSlash (value) {
                    return '/' + (value ? value : '');
                }),
            routes   = [];

        paths.forEach(function addRoutes (basePath) {
            routes = routes.concat(self._getRouteTable(basePath));
        });

        return routes;
    },

    /**
     * Router._getRouteTable(url) -> Array
     * - url (String)
     *
     * Add routes for all REST methods.
     * Inspired by http://guides.rubyonrails.org/routing.html
     **/
    _getRouteTable : function (url) {
        var resourceIdName = this._getResourceIdName(url);

        return [
            {
                // GET /resource
                method  : 'get',
                url     : url,
                handler : 'index'
            },
            {
                // GET /resource/new
                method  : 'get',
                url     : this._fixUrl(url + '/new'),
                handler : 'new'
            },
            {
                // POST /resource
                method  : 'post',
                url     : url,
                handler : 'create'
            },
            {
                // GET /resource/:resourceId
                method  : 'get',
                url     : this._fixUrl(url + '/:' + resourceIdName),
                handler : 'show'
            },
            {
                // GET /resource/:resourceId/edit
                method  : 'get',
                url     : this._fixUrl(url + '/:' + resourceIdName + '/edit'),
                handler : 'edit'
            },
            {
                // PUT /resource/:resourceId
                method  : 'put',
                url     : this._fixUrl(url + '/:' + resourceIdName),
                handler : 'update'
            },
            {
                // DELETE /resource/:resourceId
                method  : 'delete',
                url     : this._fixUrl(url + '/:' + resourceIdName),
                handler : 'destroy'
            }
        ];
    },

    /**
     * Router._getResourceName(url) -> String
     * - url (String)
     **/
    _getResourceName : function (url) {
        var parts    = url.split('/'),
            resource = parts.pop();
        return inflected.singularize(resource);
    },

    /**
     * Router._getResourceIdName(url) -> String
     * - url (String)
     **/
    _getResourceIdName : function (url) {
        if (url === '/') {
            return 'id';
        }
        var resourceName = this._getResourceName(url);
        return resourceName + 'Id';
    },

    /**
     * Router._handleRequest(url, route, controller, request, response, next)
     * - url (String)
     * - route (Object)
     * - controller (Object)
     * - request (Object): Express request object.
     * - response (Object): Express response object.
     * - next (Object): Express next object.
     **/
    _handleRequest : function (url, route, controller, request, response, next) {
        var self            = this,
            filters         = controller.getFilters(url, route.handler),
            startTime       = Date.now(),
            page            = this._getPage(request),
            controllerParts = this._parseControllerName(page),
            controllerName  = this._getControllerName(controllerParts);

        request.minorjs = {
            page         : page,
            controller   : {
              name   : controllerName,
              action : route.handler,
              parts  : controllerParts
            },
            start        : startTime,
            requestToken : Indentifier.generate()
        };

        Logger.info(request, 'Request for ' + controllerName + '#' + route.handler);

        Filter.run(filters, request, response, next)
            .then(function runController (success) {
                // call the handler and return any promises
                return self._runController(controller, route, startTime, request, response, next);
            })
            .fail(function handleError (error) {
                controller._handleError(request, response, error);
            })
            .done();
    },

    /**
     * Router._handleDevelopmentRequest(controller, url, route) -> Object
     * - controller (Object)
     * - url (String)
     * - route (Object)
     **/
    _handleDevelopmentRequest : function (controller, url, route) {
        backhoe.clearCache();

        var controllerPath = controller.path,
            Controller     = require(controllerPath),
            newController  = new Controller();

        newController.path = controllerPath;
        newController.addFiltersForHandler(url, route.handler);

        return newController;
    },

    /**
     * Router._incrementRequestCount()
     **/
    _incrementRequestCount : function () {
        this.requestCount++;

        if (this._shouldStopWorker()) {
            process.emit('message', 'shutdown');
        }
    },

    /**
     * Router._loadAllControllers(app, controllerPath, files) -> Object
     * - app (Object): Express instance.
     * - controllerPath (String): Directory containing controllers.
     * - files (Array): All controllers.
     *
     * Loads all controllers.
     **/
    _loadAllControllers : function (app, controllerPath, files) {
        var self        = this,
            controllers = [];

        files.forEach(function requireController (file) {
            controllers.push(
                self._loadController(app, controllerPath, file)
            );
        });

        return q.all(controllers);
    },

    /**
     * Router._loadController(app, controllerPath, file) -> Object
     * - app (Object): Express instance.
     * - controllerPath (String): controller directory
     * - file (String): controller pathname
     **/
    _loadController : function (app, controllerPath, file) {
        var start      = Date.now(),
            fullPath   = controllerPath + '/' + file.replace(/\.(js|coffee)/, ''),
            controller = this._requireController(fullPath);

        if (!controller) {
            return;
        }

        this._buildRoutes(app, controller, file);

        Logger.profile('Load controller ' + file, start);
    },

    /**
     * Router._parseControllerName(page) -> Array
     * - page (String)
     **/
    _parseControllerName : function (page) {
        var exclude = [ 'new', 'edit' ];

        return page
            .split('/')
            .filter(function (value) {
                // ignore IDs and new/edit
                return value.length > 0 &&
                  value.length !== 32 &&
                  isNaN(parseInt(value)) &&
                  exclude.indexOf(value) === -1;
            });
    },

    /**
     * Router._registerErrorController(app, controllerPath) -> Promise
     * - app (Object): Express app object.
     * - controllerPath (String)
     **/
    _registerErrorController : function (app, controllerPath) {
        var errorControllerPath = path.join(controllerPath, 'error');

        if (!fs.existsSync(errorControllerPath + '.js') && !fs.existsSync(errorControllerPath + '.coffee')) {
            // can't find error controller. will fall back on default Express.js
            // 404 behavior.
            return;
        }

        var controller = this._requireController(errorControllerPath),
            route      = {
                method  : 'get',
                url     : /^(.*)$/,
                handler : 'index'
            },
            url        = '/error';

        this._registerRoute(app, controller, url, route);
    },

    /**
     * Router._registerRoute(app, controller, url, route)
     * - app (Object): Express app object.
     * - controller (Object): Controller instance.
     * - url (String)
     * - route (Object): Route hash
     **/
    _registerRoute : function (app, controller, url, route) {
        var self = this;

        controller.addFiltersForHandler(url, route.handler);

        app[route.method](route.url, function (request, response, next) {
            Logger.debug(
                request,
                request.method + ' ' + request.url + ' START. ' +
                'PARAMS: ' + JSON.stringify(request.params) + ', ' +
                'BODY: ' + JSON.stringify(request.body) + ', ' +
                'QUERY: ' + JSON.stringify(request.query)
            );

            if (Environment.isDevelopment()) {
                controller = self._handleDevelopmentRequest(controller, url, route);
            }

            self._incrementRequestCount();

            self._handleRequest(url, route, controller, request, response, next);
        });
    },

    /**
     * Router._requestFinished(controller, request, startTime)
     * - controller (Object): Controller instance.
     * - request (Object): Request object.
     * - startTime (Integer): Start time in milliseconds.
     **/
    _requestFinished : function (controller, request, startTime) {
        var results = extend(
            {
                method : request.method,
                time   : Date.now() - startTime
            },
            request.minorjs
        );
        controller.emit('request-finished', results);
    },

    /**
     * Router._requireController(controllerPath) -> Object
     * - controllerPath (String): controller module
     **/
    _requireController : function (controllerPath) {
        var Controller,
            controller;

        try {
            Controller = require(controllerPath);
        } catch (error) {
            Logger.error(null, "Error while loading controller '" + controllerPath + "': " + error.stack);

            if (Environment.isWorker()) {
                process.emit('message', 'shutdown');
            } else {
                process.exit();
            }

            return;
        }

        controller      = new Controller();
        controller.path = controllerPath;

        return controller;
    },

    /**
     * Router._runController(controller, route, startTime, request, response, next) -> Object
     * - controller (Object): Controller instance.
     * - route (Object): Route hash.
     * - startTime (Integer): Start time in milliseconds.
     * - request (Object): Express request object.
     * - response (Object): Express response object.
     * - next (Object): Express next object.
     **/
    _runController : function (controller, route, startTime, request, response, next) {
        var promise = controller[route.handler]
            .call(controller, request, response, next);

        if (q.isPromise(promise)) {
            result = promise.then(this._requestFinished(controller, request, startTime));
        } else {
            this._requestFinished(controller, request, startTime);
            result = promise;
        }

        return result;
    },

    /**
     * Router._shouldStopWorker() -> Boolean
     *
     * Return true if we're a worker and we've reached the request limit.
     **/
    _shouldStopWorker : function () {
        var maxRequests;

        try {
            maxRequests = Config.get('max_requests');
        } catch (e) {
            maxRequests = 0;
        }

        return Environment.isWorker() && maxRequests > 0 && this.requestCount >= maxRequests;
    }
};

module.exports = Router;<|endoftext|>


<commit_before>Cosmos.Router = function(options) {
  // The Router defaults are dynamic values they must be read whenever an
  // instance is created, thus they are not embedded in the Class prototype
  this.options = _.extend({
    props: Cosmos.url.getParams(),
    container: document.body
  }, options);
  // defaultsProps is not applied when props are missing, but when they are
  // empty (regardless if they come from options or the default Rotuer props)
  if (_.isEmpty(this.options.props) && this.options.defaultProps) {
    this.options.props = this.options.defaultProps;
  }
  this.container = this.options.container;
  this._onPopState = this._onPopState.bind(this);
  this._bindPopStateEvent();
  // The initial render is done when the Router is instantiated
  this._load(this.options.props, window.location.href);
};
_.extend(Cosmos.Router, {
  prototype: {
    stop: function() {
      this._unbindPopStateEvent();
    },
    goTo: function(href) {
      // Old-school refreshes are made when pushState isn't supported
      if (!Cosmos.url.isPushStateSupported()) {
        window.location = href;
        return;
      }
      // The history entry for the previous Component is updated with its
      // lastest props and state, so that we resume it its exact form when/if
      // going back
      if (this._currentComponent) {
        this._replaceHistoryState(
          this._currentComponent.generateSnapshot(),
          this._currentHref);
      }
      var queryString = href.split('?').pop(),
          props = Cosmos.serialize.getPropsFromQueryString(queryString);
      // Calling pushState doesn't trigger the onpopstate event, so push state
      // events and programatic Router calls are individually handled
      // https://developer.mozilla.org/en-US/docs/Web/API/window.onpopstate
      this._load(props, href);
      this._pushHistoryState(props, href);
    },
    _load: function(props, href) {
      this._currentComponent = Cosmos.render(props, this.container);
      this._currentHref = href;
    },
    _bindPopStateEvent: function() {
      window.addEventListener('popstate', this._onPopState);
    },
    _unbindPopStateEvent: function() {
      window.removeEventListener('popstate', this._onPopState);
    },
    _onPopState: function(e) {
      // Chrome & Safari trigger an empty popState event initially, while
      // Firefox doesn't, we choose to ignore that event altogether
      if (!e.state) {
        return;
      }
      this._load(e.state, window.location.href);
    },
    _replaceHistoryState: function(props, url) {
      window.history.replaceState(props, '', url);
    },
    _pushHistoryState: function(state, url) {
      window.history.pushState(state, '', url);
    }
  }
});
<commit_msg>Make root controller public in Router instance<commit_after>Cosmos.Router = function(options) {
  // The Router defaults are dynamic values they must be read whenever an
  // instance is created, thus they are not embedded in the Class prototype
  this.options = _.extend({
    props: Cosmos.url.getParams(),
    container: document.body
  }, options);
  // defaultsProps is not applied when props are missing, but when they are
  // empty (regardless if they come from options or the default Rotuer props)
  if (_.isEmpty(this.options.props) && this.options.defaultProps) {
    this.options.props = this.options.defaultProps;
  }
  this.container = this.options.container;
  this._onPopState = this._onPopState.bind(this);
  this._bindPopStateEvent();
  // The initial render is done when the Router is instantiated
  this._load(this.options.props, window.location.href);
};
_.extend(Cosmos.Router, {
  prototype: {
    stop: function() {
      this._unbindPopStateEvent();
    },
    goTo: function(href) {
      // Old-school refreshes are made when pushState isn't supported
      if (!Cosmos.url.isPushStateSupported()) {
        window.location = href;
        return;
      }
      // The history entry for the previous Component is updated with its
      // lastest props and state, so that we resume it its exact form when/if
      // going back
      if (this.rootComponent) {
        this._replaceHistoryState(
          this.rootComponent.generateSnapshot(),
          this._currentHref);
      }
      var queryString = href.split('?').pop(),
          props = Cosmos.serialize.getPropsFromQueryString(queryString);
      // Calling pushState doesn't trigger the onpopstate event, so push state
      // events and programatic Router calls are individually handled
      // https://developer.mozilla.org/en-US/docs/Web/API/window.onpopstate
      this._load(props, href);
      this._pushHistoryState(props, href);
    },
    _load: function(props, href) {
      this.rootComponent = Cosmos.render(props, this.container);
      this._currentHref = href;
    },
    _bindPopStateEvent: function() {
      window.addEventListener('popstate', this._onPopState);
    },
    _unbindPopStateEvent: function() {
      window.removeEventListener('popstate', this._onPopState);
    },
    _onPopState: function(e) {
      // Chrome & Safari trigger an empty popState event initially, while
      // Firefox doesn't, we choose to ignore that event altogether
      if (!e.state) {
        return;
      }
      this._load(e.state, window.location.href);
    },
    _replaceHistoryState: function(props, url) {
      window.history.replaceState(props, '', url);
    },
    _pushHistoryState: function(state, url) {
      window.history.pushState(state, '', url);
    }
  }
});
<|endoftext|>


<commit_before>var _ = require('underscore')
var async = require('async')
var Battle = require('./battle')
var Bot = require('./bot')
var Engine = require('./engine')
var express = require('express')
var passport = require('passport')
var vm = require('vm')

module.exports = exports = r = new express.Router()

r.route('/my-bots')
.all(requireLogin())
.get(function(req, res, next) {
	Bot.findByAuthor(req.user, function(err, bots) {
		if(err) {
			return next(err)
		}

		res.render('my-bots', {
			user: req.user,
			bots: bots
		})
	})
})

r.route('/my-bots/new')
.all(requireLogin())
.get(function(req, res, next) {
	res.render('bot-new', {
		user: req.user
	})
})
.post(function(req, res, next) {
	var bot = new Bot()
	bot.author = req.user
	bot.name = req.body.name
	bot.code = req.body.code
	bot.save(function(err) {
		if(err) {
			return next(err)
		}

		res.redirect('/my-bots')
	})
})

r.route('/bots/:id')
.all(requireLogin())
.all(function(req, res, next) {
	Bot.findById(req.params.id, function(err, bot) {
		if(err) {
			return next(err)
		}
		if(!bot) {
			return res.send(404)
		}
		if(bot.author.toString() !== req.user.id.toString()) {
			return res.send(401)
		}

		req.bot = bot
		next()
	})
})
.get(function(req, res, next) {
	Bot.findByAuthor(req.user, function(err, bots) {
		if(err) {
			return next(err)
		}

		res.render('bot-edit', {
			user: req.user,
			bot: req.bot,
			bots: bots
		})
	})
})
.post(function(req, res, next) {
	var bot = req.bot
	bot.name = req.body.name
	bot.code = req.body.code
	bot.save(function(err) {
		if(err) {
			return next(err)
		}

		res.redirect('/my-bots')
	})
})

r.route('/test-battle')
.all(requireLogin())
.post(function(req, res, next) {
	async.auto({
		bots: function(done) {
			async.map([
				req.body.bot,
				req.body.other

			], function(id, done) {
				Bot.findById(id)
				.populate('author')
				.exec(done)
			}, done)
		},

		engine: ['bots', function(done, ctx) {
			var engine = new Engine(ctx.bots[0].codeObj, ctx.bots[1].codeObj)
			engine.play(function(err) {
				if(err) {
					return done(err)
				}

				return done(null, engine)
			})
		}],

		battle: ['bots', 'engine', function(done, ctx) {
			var battle = {
				parties: []
			}
			ctx.bots.forEach(function(bot, i) {
				battle.parties.push({
					user: bot.author,
					bot: bot,
					code: bot.code,
					pieces: ctx.engine.pieces[i],
					grid: ctx.engine.grids[i],
					winner: ctx.engine.winner.botNo === i
				})
			})
			battle.moves = ctx.engine.moves
			done(null, battle)
		}]

	}, function(err, ctx) {
		res.render('battle-view', {
			user: req.user,
			battle: ctx.battle
		})
	})
})

r.route('/')
.get(function(req, res, next) {
	if(!req.user) {
		return res.render('login')
	}

	res.redirect('/my-bots')
})

r.route('/auth/facebook')
.get(passport.authenticate('facebook', {
	scope: ['email']
}))

r.route('/auth/facebook/callback')
.get(passport.authenticate('facebook', {
	successRedirect: '/',
	failureRedirect: '/login'
}))

function requireLogin() {
	return function(req, res, next) {
		if(!req.user) {
			return res.redirect('/login')
		}

		next()
	}
}
<commit_msg>Add separate login route<commit_after>var _ = require('underscore')
var async = require('async')
var Battle = require('./battle')
var Bot = require('./bot')
var Engine = require('./engine')
var express = require('express')
var passport = require('passport')
var vm = require('vm')

module.exports = exports = r = new express.Router()

r.route('/my-bots')
.all(requireLogin())
.get(function(req, res, next) {
	Bot.findByAuthor(req.user, function(err, bots) {
		if(err) {
			return next(err)
		}

		res.render('my-bots', {
			user: req.user,
			bots: bots
		})
	})
})

r.route('/my-bots/new')
.all(requireLogin())
.get(function(req, res, next) {
	res.render('bot-new', {
		user: req.user
	})
})
.post(function(req, res, next) {
	var bot = new Bot()
	bot.author = req.user
	bot.name = req.body.name
	bot.code = req.body.code
	bot.save(function(err) {
		if(err) {
			return next(err)
		}

		res.redirect('/my-bots')
	})
})

r.route('/bots/:id')
.all(requireLogin())
.all(function(req, res, next) {
	Bot.findById(req.params.id, function(err, bot) {
		if(err) {
			return next(err)
		}
		if(!bot) {
			return res.send(404)
		}
		if(bot.author.toString() !== req.user.id.toString()) {
			return res.send(401)
		}

		req.bot = bot
		next()
	})
})
.get(function(req, res, next) {
	Bot.findByAuthor(req.user, function(err, bots) {
		if(err) {
			return next(err)
		}

		res.render('bot-edit', {
			user: req.user,
			bot: req.bot,
			bots: bots
		})
	})
})
.post(function(req, res, next) {
	var bot = req.bot
	bot.name = req.body.name
	bot.code = req.body.code
	bot.save(function(err) {
		if(err) {
			return next(err)
		}

		res.redirect('/my-bots')
	})
})

r.route('/test-battle')
.all(requireLogin())
.post(function(req, res, next) {
	async.auto({
		bots: function(done) {
			async.map([
				req.body.bot,
				req.body.other

			], function(id, done) {
				Bot.findById(id)
				.populate('author')
				.exec(done)
			}, done)
		},

		engine: ['bots', function(done, ctx) {
			var engine = new Engine(ctx.bots[0].codeObj, ctx.bots[1].codeObj)
			engine.play(function(err) {
				if(err) {
					return done(err)
				}

				return done(null, engine)
			})
		}],

		battle: ['bots', 'engine', function(done, ctx) {
			var battle = {
				parties: []
			}
			ctx.bots.forEach(function(bot, i) {
				battle.parties.push({
					user: bot.author,
					bot: bot,
					code: bot.code,
					pieces: ctx.engine.pieces[i],
					grid: ctx.engine.grids[i],
					winner: ctx.engine.winner.botNo === i
				})
			})
			battle.moves = ctx.engine.moves
			done(null, battle)
		}]

	}, function(err, ctx) {
		res.render('battle-view', {
			user: req.user,
			battle: ctx.battle
		})
	})
})

r.route('/login')
.get(function(req, res, next) {
	res.render('login')
})

r.route('/')
.get(function(req, res, next) {
	if(!req.user) {
		return res.redirect('/login')
	}

	res.redirect('/my-bots')
})

r.route('/auth/facebook')
.get(passport.authenticate('facebook', {
	scope: ['email']
}))

r.route('/auth/facebook/callback')
.get(passport.authenticate('facebook', {
	successRedirect: '/',
	failureRedirect: '/login'
}))

function requireLogin() {
	return function(req, res, next) {
		if(!req.user) {
			return res.redirect('/login')
		}

		next()
	}
}
<|endoftext|>


<commit_before>/*!
 * Router.js is reponsible for loading and consistently rendering React
 * components based on a JSON route configuration file.
 */
var url = require('url');
var BaseRouter = require('routr');
var ERROR_NAMES = {
  '400': 'BadRequest',
  '401': 'Unauthorized',
  '403': 'Forbidden',
  '404': 'NotFound',
  '409': 'Conflict',
  '410': 'Gone',
  '418': 'ImATeapot',
  '429': 'TooManyRequests',
  '500': 'InternalServerError',
  '501': 'NotImplemented',
  '502': 'BadGateway',
  '503': 'ServiceUnavailable',
  '504': 'GatewayTimeout'
};

/**
 * Creates a new instance of Router with the provided `options`. The available
 * options are:
 *
 *  - `routes`: An Object mapping arbitrary route names to descriptions of
 *    those routes. These descriptions should contain:
 *    - `path`: The absolute path to resolve to this route. If `path` contains
 *      `:var`-style parameters, those parameters will be provided to the
 *      instantiated React component as `params`. Required.
 *    - `component`: A React component class to be instantiated and rendered
 *      when this route is hit.
 *    - `method`: An optional filter based on HTTP method. _Only used for
 *      server-side routing._
 *    - `props`: An optional Object of static information to provide to the
 *      instantiated React component.
 */
function Router(options) {
  if (!(this instanceof Router)) {
    return new Router(options);
  }

  options = options || {};

  this.routes = options.routes || {};
  this.defaults = options.defaults || {};
  this.errors = options.errors || {};

  this._router = new BaseRouter(this._getRoutrTable());
}
Router.createRouter = Router;

/**
 * Builds a `routr`-compatible route table from the Router's configuration.
 */
Router.prototype._getRoutrTable = function _getRoutrTable() {
  var self = this;
  var names = Object.keys(self.routes);
  var table = {};

  names.forEach(function (name) {
    var config = self.routes[name];

    config = {
      path: config.path || self.defaults.path,
      component: config.component || self.defaults.component,
      method: 'get',
      props: config.props || self.defaults.props
    };

    if (typeof config.component !== 'function') {
      throw new Error('No component defined for "' + name + '" route.');
    }

    table[name] = config;
  });

  return table;
};

/**
 * Returns true if and only if the two `location`s passed in are on the
 * same domain.
 */
Router.prototype.isSameDomain = function isSameDomain(one, two) {
  one = url.parse(String(one));
  two = url.parse(String(two));

  return one.host && one.host === two.host;
};

/**
 * Returns a relative path to use for navigation based on the passed-in
 * `location`, a String href or Location object.
 */
Router.prototype.getPath = function getPath(location) {
  return url.parse(String(location)).pathname;
};

/**
 * Returns a route Object based on the passed-in `location`, a String href
 * or Location object.
 */
Router.prototype.getRoute = function getRoute(location) {
  var pathname = this.getPath(location);
  var route = this._router.getRoute(pathname);

  return route;
};

/**
 * Returns the top-level React Component configured for the route, based on
 * the passed-in `location`, a String href or Location object.
 */
Router.prototype.getComponent = function getComponent(location) {
  var route = this.getRoute(location);
  var component = route && route.config.component;

  if (!route) {
    return this.getErrorComponent(404);
  }

  return component({
    status: 200,
    error: null,
    route: route
  });
};

/**
 * Returns the component associated with the `errorCode` HTTP code.
 */
Router.prototype.getErrorComponent = function getErrorComponent(errorCode, message) {
  var route = this.errors[errorCode] || this.errors[ERROR_NAMES[errorCode]];
  var component = route && route.component;

  // No component is currently an unrecoverable state.
  // TODO(schoon) - Provide a fallback React component class?
  if (!component) {
    throw new Error('No component found.');
  }

  return component({
    status: errorCode,
    error: message || ERROR_NAMES[errorCode],
    route: null
  });
};

/*!
 * Export `Router`.
 */
module.exports = Router;
<commit_msg>Router: Remove unsupported option from docs.<commit_after>/*!
 * Router.js is reponsible for loading and consistently rendering React
 * components based on a JSON route configuration file.
 */
var url = require('url');
var BaseRouter = require('routr');
var ERROR_NAMES = {
  '400': 'BadRequest',
  '401': 'Unauthorized',
  '403': 'Forbidden',
  '404': 'NotFound',
  '409': 'Conflict',
  '410': 'Gone',
  '418': 'ImATeapot',
  '429': 'TooManyRequests',
  '500': 'InternalServerError',
  '501': 'NotImplemented',
  '502': 'BadGateway',
  '503': 'ServiceUnavailable',
  '504': 'GatewayTimeout'
};

/**
 * Creates a new instance of Router with the provided `options`. The available
 * options are:
 *
 *  - `routes`: An Object mapping arbitrary route names to descriptions of
 *    those routes. These descriptions should contain:
 *    - `path`: The absolute path to resolve to this route. If `path` contains
 *      `:var`-style parameters, those parameters will be provided to the
 *      instantiated React component as `params`. Required.
 *    - `component`: A React component class to be instantiated and rendered
 *      when this route is hit.
 *    - `props`: An optional Object of static information to provide to the
 *      instantiated React component.
 */
function Router(options) {
  if (!(this instanceof Router)) {
    return new Router(options);
  }

  options = options || {};

  this.routes = options.routes || {};
  this.defaults = options.defaults || {};
  this.errors = options.errors || {};

  this._router = new BaseRouter(this._getRoutrTable());
}
Router.createRouter = Router;

/**
 * Builds a `routr`-compatible route table from the Router's configuration.
 */
Router.prototype._getRoutrTable = function _getRoutrTable() {
  var self = this;
  var names = Object.keys(self.routes);
  var table = {};

  names.forEach(function (name) {
    var config = self.routes[name];

    config = {
      path: config.path || self.defaults.path,
      component: config.component || self.defaults.component,
      method: 'get',
      props: config.props || self.defaults.props
    };

    if (typeof config.component !== 'function') {
      throw new Error('No component defined for "' + name + '" route.');
    }

    table[name] = config;
  });

  return table;
};

/**
 * Returns true if and only if the two `location`s passed in are on the
 * same domain.
 */
Router.prototype.isSameDomain = function isSameDomain(one, two) {
  one = url.parse(String(one));
  two = url.parse(String(two));

  return one.host && one.host === two.host;
};

/**
 * Returns a relative path to use for navigation based on the passed-in
 * `location`, a String href or Location object.
 */
Router.prototype.getPath = function getPath(location) {
  return url.parse(String(location)).pathname;
};

/**
 * Returns a route Object based on the passed-in `location`, a String href
 * or Location object.
 */
Router.prototype.getRoute = function getRoute(location) {
  var pathname = this.getPath(location);
  var route = this._router.getRoute(pathname);

  return route;
};

/**
 * Returns the top-level React Component configured for the route, based on
 * the passed-in `location`, a String href or Location object.
 */
Router.prototype.getComponent = function getComponent(location) {
  var route = this.getRoute(location);
  var component = route && route.config.component;

  if (!route) {
    return this.getErrorComponent(404);
  }

  return component({
    status: 200,
    error: null,
    route: route
  });
};

/**
 * Returns the component associated with the `errorCode` HTTP code.
 */
Router.prototype.getErrorComponent = function getErrorComponent(errorCode, message) {
  var route = this.errors[errorCode] || this.errors[ERROR_NAMES[errorCode]];
  var component = route && route.component;

  // No component is currently an unrecoverable state.
  // TODO(schoon) - Provide a fallback React component class?
  if (!component) {
    throw new Error('No component found.');
  }

  return component({
    status: errorCode,
    error: message || ERROR_NAMES[errorCode],
    route: null
  });
};

/*!
 * Export `Router`.
 */
module.exports = Router;
<|endoftext|>


<commit_before>var fs = require('fs');
var filePath = require('path');
var getContentType = require(__dirname + '/content-type.js');

module.exports = exports = new Router();
function Router() {

  this.routes = {
    'GET': {},
    'POST': {},
    'PUT': {},
    'PATCH': {},
    'DELETE': {},
    'ERROR': function(req, res) {
      res.writeHead(404, {'Content-Type': 'application/json'});
      res.write(JSON.stringify({msg: 'Page not found'}));
      return res.end();
    }
  };
}

(function(){
  this.get = function(route, cbinput) {

    function getCallback(req, res){
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.write(cbinput);
      res.end();
    }

    var callback = getCallback;

    if (typeof cbinput === 'function'){
      callback = cbinput;
    }

    this.routes['GET'][route] = callback;
  };

  this.getStatic = function(file, route, cb){
      var filePathCb = function filePathCb(req, res){
        var readStream = fs.createReadStream(file);
        var body = '';
        readStream.on('data', function(chunk){
          body += chunk.toString();
        });
        readStream.on('end', function(){
          res.writeHead(200, {'Content-Type': getContentType(file)});
          res.write(body);
          res.end();
        });
      };
      route = route || '/'+ filePath.basename(file);
      var callback = cb || filePathCb;
      this.routes['GET'][route] = callback;
  };

  this.post = function(route, cb) {

    function postCallback(req, res){
      var concatData = '';
      req.on('data', function(data){
        concatData += data.toString();
      });
      req.on('end', function() {
        res.writeHead(200, {"Content-Type": "application/json"});
        res.write(concatData);
        res.end();
      });
    }
    var callback =  cb || postCallback;

    this.routes['POST'][route] = callback;
  };

   this.error = function(req, res){
        res.writeHead(404, {'Content-Type': 'text/plain'});
        res.write('Page not found.');
        res.end();
    };

  Router.prototype.route = function(options) {
  return (req, res) => {
    res.wrend = (obj) => {
      res.write(obj);
      res.end();
    };
    var routeFunction = this.routes[req.method][req.url] || this.routes.ERROR;
    routeFunction(req, res);
  };
};

   this.route = function(req, res) {
      (this.routes[req.method][req.url] || this.error)(req, res);
   };

}).call(Router.prototype);
<commit_msg>revise router.js<commit_after>var fs = require('fs');
var filePath = require('path');
var getContentType = require(__dirname + '/content-type.js');

module.exports = exports = new Router();
function Router() {

  this.routes = {
    'GET': {},
    'POST': {},
    'PUT': {},
    'PATCH': {},
    'DELETE': {}
  };
}

(function() {
  this.get = function(route, cbinput) {
    function getCallback(req, res) {
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      res.write(cbinput);
      res.end();
    }

    var callback = getCallback;

    if (typeof cbinput === 'function') {
      callback = cbinput;
    }

    this.routes['GET'][route] = callback;
  };

  this.getStatic = function(file, route, cb) {
    var filePathCb = function filePathCb(req, res) {
      var readStream = fs.createReadStream(file);
      var body = '';
      readStream.on('data', (chunk) => {
        body += chunk.toString();
      });
      readStream.on('end', function() {
        res.writeHead(200, { 'Content-Type': getContentType(file) });
        res.write(body);
        res.end();
      });
    };
    route = route || '/' + filePath.basename(file);
    var callback = cb || filePathCb;
    this.routes['GET'][route] = callback;
  };

  this.post = function(route, cb) {
    function postCallback(req, res) {
      var concatData = '';
      req.on('data', (data) => {
        concatData += data.toString();
      });
      req.on('end', () => {
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.write(concatData);
        res.end();
      });
    }
    var callback = cb || postCallback;

    this.routes['POST'][route] = callback;
  };

  this.error = function(req, res) {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.write('Error. Page not found.');
    res.end();
  };

  this.route = function(req, res) {
    (this.routes[req.method][req.url] || this.error)(req, res);
  };
}).call(Router.prototype);
<|endoftext|>


<commit_before>(function() {
"use strict";
var config,util,postcss;

var RTLCSS = (function() {
  function RTLCSS(options, rules, declarations, properties) {
    postcss = require('postcss');
    config  = require('./config.js').configure(options, rules, declarations, properties);
    util    = require('./util.js').configure(config);
  }
  RTLCSS.prototype.process = function(css, options) {
    return postcss(this.postcss).process(css,options);
  };
  RTLCSS.prototype.postcss = function (css) {
    css.eachRule(function (rule, idx) {
      var previousComment = { 'text': '', removeSelf: function () { } };
      if (idx > 0 && rule.parent.rules[idx - 1].type == 'comment')
        previousComment = rule.parent.rules[idx - 1];

      //processing instruction at rule level
      for (var x = 0; x < config.instructions.rules.length; x++) {
        var pi = config.instructions.rules[x];
        if (("/*" + previousComment.text + "*/").match(pi.expr) && pi.action(rule)) {
          util.logRuleAction(rule, pi);
          if(!config.preserveDirectives)
            previousComment.removeSelf();
          return;
        }
      }

      var flipped = 0;
      rule.eachDecl(function (decl, index) {
        if (decl.type == "comment")
          return;

        //processing instruction at declaration level
        for (var x = 0; x < config.instructions.declarations.length; x++) {
          var pi = config.instructions.declarations[x];
          if (decl._value && decl._value.raw && decl._value.raw.match(pi.expr) && pi.action(decl)) {
            util.logDeclAction(decl, pi);
            return;
          }
        }

        //processing instruction at property level
        for (var x = 0; x < config.instructions.properties.length; x++) {
          var pi = config.instructions.properties[x];
          if (decl.prop.match(pi.expr)) {
            var rawValue = config.preserveComments && decl._value && decl._value.raw ? decl._value.raw : decl.value;
            var result;
            if (config.preserveComments) {
              var commentsLessRawValue = util.saveComments(rawValue);
              result = pi.action(decl.prop, commentsLessRawValue);
              result.value = util.restoreComments(result.value);
            }
            else
              result = pi.action(decl.prop, rawValue);

            if (result.prop != decl.prop || result.value != rawValue) {
              flipped++;
              util.logPropAction(decl, result, pi);
              decl.prop = result.prop;
              decl.value = result.value;
            }
            break;
          }
        }
      });

      if (config.autoRename && flipped == 0)
        rule.selector = util.swapLeftRight(util.swapLtrRtl(util.swapWestEast(rule.selector)));
      return;
    });
    if (config.minify) {
      css.eachDecl(function (decl) {
        decl.before = '';
        decl.between = ':';
        if (decl._value.raw)
          decl._value.raw = decl.value;
      });
      css.eachRule(function (rule) {
        rule.before = '';
        rule.between = '';
        rule.after = '';
      });
      css.eachAtRule(function (atRule) {
        atRule.before = '';
        atRule.between = '';
        atRule.after = '';
      });
      css.eachComment(function (comment) {
        comment.removeSelf();
      });
    }
  };
  return RTLCSS;
})();

var rtlcss = function(options, rules, declarations, properties) {
  return new RTLCSS(options, rules, declarations, properties);
};

rtlcss.process = function(css, options, rules, declarations, properties){
  return new RTLCSS(options, rules, declarations, properties).process(css).css;
}

rtlcss.configure = function(config){
  config = config || {};
  return new RTLCSS(config.options, config.rules, config.declarations, config.properties);
}

module.exports = rtlcss;

}).call(this);<commit_msg>Add comments to the exported methods<commit_after>(function() {
"use strict";
var config,util,postcss;

var RTLCSS = (function() {
  function RTLCSS(options, rules, declarations, properties) {
    postcss = require('postcss');
    config  = require('./config.js').configure(options, rules, declarations, properties);
    util    = require('./util.js').configure(config);
  }
  RTLCSS.prototype.process = function(css, options) {
    return postcss(this.postcss).process(css,options);
  };
  RTLCSS.prototype.postcss = function (css) {
    css.eachRule(function (rule, idx) {
      var previousComment = { 'text': '', removeSelf: function () { } };
      if (idx > 0 && rule.parent.rules[idx - 1].type == 'comment')
        previousComment = rule.parent.rules[idx - 1];

      //processing instruction at rule level
      for (var x = 0; x < config.instructions.rules.length; x++) {
        var pi = config.instructions.rules[x];
        if (("/*" + previousComment.text + "*/").match(pi.expr) && pi.action(rule)) {
          util.logRuleAction(rule, pi);
          if(!config.preserveDirectives)
            previousComment.removeSelf();
          return;
        }
      }

      var flipped = 0;
      rule.eachDecl(function (decl, index) {
        if (decl.type == "comment")
          return;

        //processing instruction at declaration level
        for (var x = 0; x < config.instructions.declarations.length; x++) {
          var pi = config.instructions.declarations[x];
          if (decl._value && decl._value.raw && decl._value.raw.match(pi.expr) && pi.action(decl)) {
            util.logDeclAction(decl, pi);
            return;
          }
        }

        //processing instruction at property level
        for (var x = 0; x < config.instructions.properties.length; x++) {
          var pi = config.instructions.properties[x];
          if (decl.prop.match(pi.expr)) {
            var rawValue = config.preserveComments && decl._value && decl._value.raw ? decl._value.raw : decl.value;
            var result;
            if (config.preserveComments) {
              var commentsLessRawValue = util.saveComments(rawValue);
              result = pi.action(decl.prop, commentsLessRawValue);
              result.value = util.restoreComments(result.value);
            }
            else
              result = pi.action(decl.prop, rawValue);

            if (result.prop != decl.prop || result.value != rawValue) {
              flipped++;
              util.logPropAction(decl, result, pi);
              decl.prop = result.prop;
              decl.value = result.value;
            }
            break;
          }
        }
      });

      if (config.autoRename && flipped == 0)
        rule.selector = util.swapLeftRight(util.swapLtrRtl(util.swapWestEast(rule.selector)));
      return;
    });
    if (config.minify) {
      css.eachDecl(function (decl) {
        decl.before = '';
        decl.between = ':';
        if (decl._value.raw)
          decl._value.raw = decl.value;
      });
      css.eachRule(function (rule) {
        rule.before = '';
        rule.between = '';
        rule.after = '';
      });
      css.eachAtRule(function (atRule) {
        atRule.before = '';
        atRule.between = '';
        atRule.after = '';
      });
      css.eachComment(function (comment) {
        comment.removeSelf();
      });
    }
  };
  return RTLCSS;
})();

/**
 * Creates a new RTLCSS instance.
 *
 * @options	{Object}	An object containing RTLCSS settings.
 * @rules	{Object}	An object containing RTLCSS rule level processing directives.
 * @declarations	{Object}	An object containing RTLCSS declaration level processing directives.
 * @properties	{Object}	An object containing RTLCSS property level processing directives.
 *
 * @return {Object} new RTLCSS instance.
 */
var exports = function(options, rules, declarations, properties) {
  return new RTLCSS(options, rules, declarations, properties);
};

/**
 * Creates a new RTLCSS instance, process the input and return its result.
 *
 * @css	{String}	A string containing input CSS.
 * @options	{Object}	An object containing RTLCSS settings.
 * @rules	{Object}	An object containing RTLCSS rule level processing directives.
 * @declarations	{Object}	An object containing RTLCSS declaration level processing directives.
 * @properties	{Object}	An object containing RTLCSS property level processing directives.
 *
 * @return	{String}	A string contining the RTLed css.
 */
exports.process = function(css, options, rules, declarations, properties){
  return new RTLCSS(options, rules, declarations, properties).process(css).css;
}

/**
 * Creates a new instance of RTLCSS using the passed configuration object
 *
 * @config	{Object}	An object containing RTLCSS options, rules, declarations and properties processing directives.
 *
 * @return	{Object}	A new RTLCSS instance.
 */
exports.configure = function(config){
  config = config || {};
  return new RTLCSS(config.options, config.rules, config.declarations, config.properties);
}

module.exports = exports;

}).call(this);<|endoftext|>