<commit_before>var nodemailer  = require('nodemailer'),
    express     = require('express'),
    flatten     = require('flatten.js').flatten,
    path        = require('path'),
    app         = express(),
    hbs         = require('./hbs'),
    options     = require('./config'),
    store       = require('./store')(options.store),
    versionTest = require('./session-version'),
    undefsafe   = require('undefsafe'),
    models      = require('./models').createModels(store),
    routes      = require('./routes'),
    handlers    = require('./handlers'),
    middleware  = require('./middleware'),
    metrics     = require('./metrics'),
    url         = require('url'),
    github      = require('./github')(options), // if used, contains github.id
    _           = require('underscore'),
    crypto      = require('crypto'),
    flattened,
    generateSessionSecret = function () {
      'use strict';
      console.log('Warning: Generating a session key - please see http://jsbin.com/help/session-secret');
      return crypto.createHash('md5').update(Math.random() + '').digest('hex');
    };

/**
 * JS Bin configuration
 */

app.store  = store;
// Create model singletons
// models.createModels(store);

app.mailer = (function (mail) {
  var mailTransport = null,
      method   = mail && mail.adapter,
      settings = mail && mail[method];

  if (method && options) {
    mailTransport = nodemailer.createTransport(method, settings);
  }

  return new handlers.MailHandler(mailTransport, app.render.bind(app));
})(options.mail);

app.PRODUCTION  = 'production';
app.DEVELOPMENT = 'development';

// Set the NODE_ENV variable as this is used by Express, we want the
// environment to take precedence but allow it to be set using the config file
// too.
if (process.env.NODE_ENV) {
  options.env = process.env.NODE_ENV;
}
process.env.NODE_ENV = options.env;

// Need to set the node environment to run in the same timezone as the database
// This will ideally be UTC in both cases but if not this can be set either
// using the TZ environment variable or the "timezone" option.
// This is because the mysql library coerces MySQL dates (without timezones)
// into JavaScript date objects.
if (!process.env.TZ && options.timezone) {
  process.env.TZ = options.timezone;
}

// Sort out the port.
(function () {
  var port = process.env.PORT;

  // if we're running from the bin/jsbin file, then we modify
  // both the listen port AND the options.url
  if (process.env.JSBIN_PORT) {
    if (options.url.host.indexOf(':') === -1) {
      options.url.host += ':' + process.env.JSBIN_PORT;
    } else {
      options.url.host = options.url.host.replace(/\:\d+$/, function () {
        return ':' + process.env.JSBIN_PORT;
      });
    }
  }

  if (!port) {
    options.url.host.replace(/\:(\d+)$/, function (m, p) {
      if (p.length) {
        port = p;
      }
    });
  }

  if (!port) {
    port = 80;
  }

  // NOTE: this is *only* used for running the server.listen()
  // it's not used in the urls to access assets, etc.
  options.port = port;
})();

// Strip trailing slash from the prefix
options.url.prefix = options.url.prefix.replace(/\/$/, '');

// Apply the keys from the config file. All nested properties are
// space delimited to match the express style.
//
// For example, app.set('url prefix'); //=> '/'
flattened = flatten(options, ' ');

Object.getOwnPropertyNames(flattened).forEach(function (key) {
  app.set(key, flattened[key]);
});

// in live, we run behind a proxy - so this will give us our IPs again:
// http://expressjs.com/guide.html#proxies
if (process.env.NODE_ENV === app.PRODUCTION || process.env.JSBIN_PROXY) {
  app.enable('trust proxy');
}

app.set('root', path.resolve(path.join(__dirname, '..')));

// ensure jsbin is running from the expected root
process.chdir(app.set('root'));

app.set('version', require('../package').version);

app.set('view engine', 'html');
app.set('views', path.join(app.set('root'), 'views'));
app.set('url prefix', options.url.prefix);
app.set('url ssl', options.url.ssl);
app.set('url full', 'http://' + app.set('url host') + app.set('url prefix'));
app.set('basepath', app.set('url prefix'));
app.set('is_production', app.get('env') === app.PRODUCTION);

if (options.url.static) {
  app.set('static url', 'http://' + app.set('url static'));
} else {
  app.set('static url', app.set('url full'));
}

if (options.url.runner) {
  // strip trailing slash, just in case
  options.url.runner = options.url.runner.replace(/\/$/, '');
  app.set('url runner', options.url.runner);
} else {
  app.set('url runner', app.set('url full'));
}

app.set('views', 'views');
app.set('view engine', 'html');
app.engine('html', hbs.__express);
app.engine('txt', hbs.__express); // used in email

// Define some generic template variables.
app.locals({
  version: app.get('version'),
  client: options.client,
});

app.connect = function (callback) {
  app.emit('before', app);

  // Register all the middleware.
  app.configure(function () {
    var mount = app.set('url prefix') || '/',
        logger;

    logger = process.env.JSBIN_LOGGER || app.set('server logger') || 'tiny';

    if (logger !== 'none') {
      app.use(express.logger(logger));
    }

    // Redirect gist.jsbin urls to /gist/:id
    app.use(function (req, res, next) {
      if (req.headers.host.match(/gist.jsbin/)) {
        var parsedUrl = url.parse(req.originalUrl),
            segments = parsedUrl.pathname.split('/'),
            gistId = segments.slice(-1).join('');
        return res.redirect((app.get('url ssl') ? 'https://' : 'http://') + options.url.host + '/gist/' + gistId);
      }
      next();
    });
    app.use(mount, (function () {
      var staticRouter = express.static(path.join(app.set('root'), 'public'));

      return function (req, res, next) {
        var url = req.protocol + '://' + req.get('host') + req.url;
        if (options.url.static) {
          if (url.indexOf(options.url.static) === -1) {
            return next();
          }
        }

        return staticRouter(req, res, next);
      };
    })());
    app.use(middleware.limitContentLength({limit: app.set('max-request-size')}));
    var sessionSecret = app.get('session secret') || generateSessionSecret();
    var oldCookieParser = express.cookieParser('supersecret');
    var newCookieParser = express.cookieParser('newsupersecret');
    app.use(function (req, res, next){
      function wrappedNext (err) {
        if (!err) {
          console.log('new session, all bless');
          return next();
        }
        console.log('old session');
        oldCookieParser(req, res, function(err) {
          if (err) {
            return next(err);
          }
          res.flash(res.flash.NOTIFICATION, 'We\'ve updated security, please sign in again');
          res.redirect('/login');
        });

      }
      return newCookieParser(req, res, wrappedNext);
    });
    app.use(express.cookieSession({
      key: 'jsbin',
      cookie: {
        maxAge: 365 * 24 * 60 * 60 * 1000,
        domain: app.get('url host').indexOf('.') === -1 ? undefined : '.' + app.get('url host')
      }
    }));
    app.use(function (req, res, next) {
      // Deletes cookies using the old domain (without the leading '.')
      // and we know this because they don't have a version in their cookie.
      if (undefsafe(req, 'session.version') === undefined) {
        var oldSess = _.extend({ version: app.get('version') }, req.session);
        res.clearCookie('jsbin');
        req.session = oldSess;
      }

      next();
    });
    // Passport
    if (options.github && options.github.id) {
      github.initialize(app);
    }
    app.use(express.urlencoded());
    app.use(express.json());
    app.use(middleware.csrf({ ignore: ['/', /^\/api\//] }));
    app.use(middleware.api({ app: app }));
    app.use(middleware.subdomain(app));
    app.use(middleware.noslashes());
    app.use(middleware.ajax());
    app.use(middleware.cors());
    app.use(middleware.jsonp());
    app.use(middleware.flash());
    app.use(middleware.protocolCheck);
    app.use(mount, app.router);

    // Register all routes
    routes(app);
  });

  app.emit('after', app);

  store.connect(function (err) {
    if (err) {
      metrics.increment('error.store.connect');
      throw err;
    }

    var port = app.set('port');
    module.exports.listen(port);

    if (typeof callback === 'function') {
      callback();
    }
    app.emit('connected');

    process.stdout.write('JS Bin v' + app.set('version') + ' is up and running on port ' + app.set('port') + '. Now point your browser at ' + app.set('url full') + '\n');
  });
};

// Export the application to allow it to be included.
module.exports = app;

// Run a local development server if this file is called directly.
if (require.main === module) {
  app.connect();
}
<commit_msg>Debugging<commit_after>var nodemailer  = require('nodemailer'),
    express     = require('express'),
    flatten     = require('flatten.js').flatten,
    path        = require('path'),
    app         = express(),
    hbs         = require('./hbs'),
    options     = require('./config'),
    store       = require('./store')(options.store),
    versionTest = require('./session-version'),
    undefsafe   = require('undefsafe'),
    models      = require('./models').createModels(store),
    routes      = require('./routes'),
    handlers    = require('./handlers'),
    middleware  = require('./middleware'),
    metrics     = require('./metrics'),
    url         = require('url'),
    github      = require('./github')(options), // if used, contains github.id
    _           = require('underscore'),
    crypto      = require('crypto'),
    flattened,
    generateSessionSecret = function () {
      'use strict';
      console.log('Warning: Generating a session key - please see http://jsbin.com/help/session-secret');
      return crypto.createHash('md5').update(Math.random() + '').digest('hex');
    };

/**
 * JS Bin configuration
 */

app.store  = store;
// Create model singletons
// models.createModels(store);

app.mailer = (function (mail) {
  var mailTransport = null,
      method   = mail && mail.adapter,
      settings = mail && mail[method];

  if (method && options) {
    mailTransport = nodemailer.createTransport(method, settings);
  }

  return new handlers.MailHandler(mailTransport, app.render.bind(app));
})(options.mail);

app.PRODUCTION  = 'production';
app.DEVELOPMENT = 'development';

// Set the NODE_ENV variable as this is used by Express, we want the
// environment to take precedence but allow it to be set using the config file
// too.
if (process.env.NODE_ENV) {
  options.env = process.env.NODE_ENV;
}
process.env.NODE_ENV = options.env;

// Need to set the node environment to run in the same timezone as the database
// This will ideally be UTC in both cases but if not this can be set either
// using the TZ environment variable or the "timezone" option.
// This is because the mysql library coerces MySQL dates (without timezones)
// into JavaScript date objects.
if (!process.env.TZ && options.timezone) {
  process.env.TZ = options.timezone;
}

// Sort out the port.
(function () {
  var port = process.env.PORT;

  // if we're running from the bin/jsbin file, then we modify
  // both the listen port AND the options.url
  if (process.env.JSBIN_PORT) {
    if (options.url.host.indexOf(':') === -1) {
      options.url.host += ':' + process.env.JSBIN_PORT;
    } else {
      options.url.host = options.url.host.replace(/\:\d+$/, function () {
        return ':' + process.env.JSBIN_PORT;
      });
    }
  }

  if (!port) {
    options.url.host.replace(/\:(\d+)$/, function (m, p) {
      if (p.length) {
        port = p;
      }
    });
  }

  if (!port) {
    port = 80;
  }

  // NOTE: this is *only* used for running the server.listen()
  // it's not used in the urls to access assets, etc.
  options.port = port;
})();

// Strip trailing slash from the prefix
options.url.prefix = options.url.prefix.replace(/\/$/, '');

// Apply the keys from the config file. All nested properties are
// space delimited to match the express style.
//
// For example, app.set('url prefix'); //=> '/'
flattened = flatten(options, ' ');

Object.getOwnPropertyNames(flattened).forEach(function (key) {
  app.set(key, flattened[key]);
});

// in live, we run behind a proxy - so this will give us our IPs again:
// http://expressjs.com/guide.html#proxies
if (process.env.NODE_ENV === app.PRODUCTION || process.env.JSBIN_PROXY) {
  app.enable('trust proxy');
}

app.set('root', path.resolve(path.join(__dirname, '..')));

// ensure jsbin is running from the expected root
process.chdir(app.set('root'));

app.set('version', require('../package').version);

app.set('view engine', 'html');
app.set('views', path.join(app.set('root'), 'views'));
app.set('url prefix', options.url.prefix);
app.set('url ssl', options.url.ssl);
app.set('url full', 'http://' + app.set('url host') + app.set('url prefix'));
app.set('basepath', app.set('url prefix'));
app.set('is_production', app.get('env') === app.PRODUCTION);

if (options.url.static) {
  app.set('static url', 'http://' + app.set('url static'));
} else {
  app.set('static url', app.set('url full'));
}

if (options.url.runner) {
  // strip trailing slash, just in case
  options.url.runner = options.url.runner.replace(/\/$/, '');
  app.set('url runner', options.url.runner);
} else {
  app.set('url runner', app.set('url full'));
}

app.set('views', 'views');
app.set('view engine', 'html');
app.engine('html', hbs.__express);
app.engine('txt', hbs.__express); // used in email

// Define some generic template variables.
app.locals({
  version: app.get('version'),
  client: options.client,
});

app.connect = function (callback) {
  app.emit('before', app);

  // Register all the middleware.
  app.configure(function () {
    var mount = app.set('url prefix') || '/',
        logger;

    logger = process.env.JSBIN_LOGGER || app.set('server logger') || 'tiny';

    if (logger !== 'none') {
      app.use(express.logger(logger));
    }

    // Redirect gist.jsbin urls to /gist/:id
    app.use(function (req, res, next) {
      if (req.headers.host.match(/gist.jsbin/)) {
        var parsedUrl = url.parse(req.originalUrl),
            segments = parsedUrl.pathname.split('/'),
            gistId = segments.slice(-1).join('');
        return res.redirect((app.get('url ssl') ? 'https://' : 'http://') + options.url.host + '/gist/' + gistId);
      }
      next();
    });
    app.use(mount, (function () {
      var staticRouter = express.static(path.join(app.set('root'), 'public'));

      return function (req, res, next) {
        var url = req.protocol + '://' + req.get('host') + req.url;
        if (options.url.static) {
          if (url.indexOf(options.url.static) === -1) {
            return next();
          }
        }

        return staticRouter(req, res, next);
      };
    })());
    app.use(middleware.limitContentLength({limit: app.set('max-request-size')}));
    var sessionSecret = app.get('session secret') || generateSessionSecret();
    var oldCookieParser = express.cookieParser('supersecret');
    var newCookieParser = express.cookieParser('newsupersecret');
    app.use(function (req, res, next){
      function wrappedNext (err) {
        if (!err) {
          console.log('new session, all bless');
          console.log(req.signedCookies);
          return next();
        }
        console.log('old session');
        oldCookieParser(req, res, function(err) {
          if (err) {
            return next(err);
          }
          res.flash(res.flash.NOTIFICATION, 'We\'ve updated security, please sign in again');
          res.redirect('/login');
        });

      }
      return newCookieParser(req, res, wrappedNext);
    });
    app.use(express.cookieSession({
      key: 'jsbin',
      cookie: {
        maxAge: 365 * 24 * 60 * 60 * 1000,
        domain: app.get('url host').indexOf('.') === -1 ? undefined : '.' + app.get('url host')
      }
    }));
    app.use(function (req, res, next) {
      // Deletes cookies using the old domain (without the leading '.')
      // and we know this because they don't have a version in their cookie.
      if (undefsafe(req, 'session.version') === undefined) {
        var oldSess = _.extend({ version: app.get('version') }, req.session);
        res.clearCookie('jsbin');
        req.session = oldSess;
      }

      next();
    });
    // Passport
    if (options.github && options.github.id) {
      github.initialize(app);
    }
    app.use(express.urlencoded());
    app.use(express.json());
    app.use(middleware.csrf({ ignore: ['/', /^\/api\//] }));
    app.use(middleware.api({ app: app }));
    app.use(middleware.subdomain(app));
    app.use(middleware.noslashes());
    app.use(middleware.ajax());
    app.use(middleware.cors());
    app.use(middleware.jsonp());
    app.use(middleware.flash());
    app.use(middleware.protocolCheck);
    app.use(mount, app.router);

    // Register all routes
    routes(app);
  });

  app.emit('after', app);

  store.connect(function (err) {
    if (err) {
      metrics.increment('error.store.connect');
      throw err;
    }

    var port = app.set('port');
    module.exports.listen(port);

    if (typeof callback === 'function') {
      callback();
    }
    app.emit('connected');

    process.stdout.write('JS Bin v' + app.set('version') + ' is up and running on port ' + app.set('port') + '. Now point your browser at ' + app.set('url full') + '\n');
  });
};

// Export the application to allow it to be included.
module.exports = app;

// Run a local development server if this file is called directly.
if (require.main === module) {
  app.connect();
}
<|endoftext|>


<commit_before>/*
* Created with hexamap.
* User: bretshack
* Date: 2014-05-19
* Time: 09:04 PM
*/

define(["app/getScreenCenter", "app/coordinates", "svg.min", "app/hexagon"], function(getScreenCenter, coordinates, SVG, Hexagon) {
  var canvas = SVG('canvas')
  var centerx = getScreenCenter.x;
  var centery = getScreenCenter.y;
  var size = 30;
  var shifty = size * 3/2;
  var shiftx = Math.sqrt(3)/2* size;

  var grid = [];
  var griddraw = canvas.group();

  var col = 9;
  var row = -9;
  for (col=9;col>=-9;col--) {
    for (row=-9;row<=9;row++) {
      var hex = new Hexagon(centerx+(shiftx*col*2),centery+(shifty*row*2),size,col,row);
      grid.push(hex);
      griddraw.add(canvas.polygon(hex.path).fill('none').stroke({ width: 3 }));
      alert(col + ", " + row);
    }
  }

  /*
  var hex00 = new Hexagon(centerx,centery,size, 0, 0);

  //var hex00draw = canvas.polygon(hex00.path).fill('none').stroke({ width: 3 });
  griddraw.add(canvas.polygon(hex00.path).fill('none').stroke({ width: 3 }));

  var hex0_1 = new Hexagon(centerx+(shiftx),centery+(shifty),size);
  var hex0_1draw = canvas.polygon(hex0_1.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_1draw);

  var hex0_2 = new Hexagon(centerx+(shiftx*2),centery+(shifty*2),size);
  var hex0_2draw = canvas.polygon(hex0_2.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_2draw);

  var hex0_3 = new Hexagon(centerx+(shiftx*3),centery+(shifty*3),size);
  var hex0_3draw = canvas.polygon(hex0_3.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_3draw);

  var hex0_4 = new Hexagon(centerx+(shiftx*4),centery+(shifty*4),size);
  var hex0_4draw = canvas.polygon(hex0_4.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_4draw);

  var hex0_5 = new Hexagon(centerx+(shiftx*5),centery+(shifty*5),size);
  var hex0_5draw = canvas.polygon(hex0_5.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_5draw);

  var hex0_6 = new Hexagon(centerx+(shiftx*6),centery+(shifty*6),size);
  var hex0_6draw = canvas.polygon(hex0_6.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_6draw);

  var hex0_7 = new Hexagon(centerx+(shiftx*7),centery+(shifty*7),size);
  var hex0_7draw = canvas.polygon(hex0_7.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_4draw);

  var hex0_8 = new Hexagon(centerx+(shiftx*8),centery+(shifty*8),size);
  var hex0_8draw = canvas.polygon(hex0_8.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_4draw);

  var hex0_9 = new Hexagon(centerx-(shiftx*9),centery-(shifty*9), size);
  var hex0_9draw = canvas.polygon(hex0_9.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_9draw);

  var hex9_9 = new Hexagon(centerx+(shiftx*9),centery-(shifty*9), size);
  var hex9_9draw = canvas.polygon(hex9_9.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex9_9draw);

  var hex90 = new Hexagon(centerx+(shiftx*18),centery, size);
  var hex90draw = canvas.polygon(hex90.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex90draw);

  var hex09 = new Hexagon(centerx+(shiftx*9),centery+(shifty*9), size);
  var hex09draw = canvas.polygon(hex09.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex09draw);

  var hex_99 = new Hexagon(centerx-(shiftx*9),centery+(shifty*9), size);
  var hex_99draw = canvas.polygon(hex_99.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex_99draw);

  var hex_90 = new Hexagon(centerx-(shiftx*18),centery, size);
  var hex_90draw = canvas.polygon(hex_90.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex_90draw);

*/
});<commit_msg>Changed the grid algorithm<commit_after>/*
* Created with hexamap.
* User: bretshack
* Date: 2014-05-19
* Time: 09:04 PM
*/

define(["app/getScreenCenter", "app/coordinates", "svg.min", "app/hexagon"], function(getScreenCenter, coordinates, SVG, Hexagon) {
  var canvas = SVG('canvas')
  var centerx = getScreenCenter.x;
  var centery = getScreenCenter.y;
  var size = 30;
  var shifty = size * 3/2;
  var shiftx = Math.sqrt(3)/2* size;

  var grid = [];
  var griddraw = canvas.group();

  var col = 9;
  var row = -9;
  for (col=9;col>=-9;col--) {
    for (row=-9;row<=9;row++) {
      if (abs(row)%2===0) {
        var hex = new Hexagon(centerx+(shiftx*col*2),centery+(shifty*row),size,col,row);
        grid.push(hex);
        griddraw.add(canvas.polygon(hex.path).fill('none').stroke({ width: 3 }));
      }
      else {
        var hex = new Hexagon(centerx+(shiftx*col),centery+(shifty*row*2),size,col,row);
        grid.push(hex);
        griddraw.add(canvas.polygon(hex.path).fill('none').stroke({ width: 3 }));
      }
      alert(col + ", " + row);

    }
  }

  /*
  var hex00 = new Hexagon(centerx,centery,size, 0, 0);

  //var hex00draw = canvas.polygon(hex00.path).fill('none').stroke({ width: 3 });
  griddraw.add(canvas.polygon(hex00.path).fill('none').stroke({ width: 3 }));

  var hex0_1 = new Hexagon(centerx+(shiftx),centery+(shifty),size);
  var hex0_1draw = canvas.polygon(hex0_1.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_1draw);

  var hex0_2 = new Hexagon(centerx+(shiftx*2),centery+(shifty*2),size);
  var hex0_2draw = canvas.polygon(hex0_2.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_2draw);

  var hex0_3 = new Hexagon(centerx+(shiftx*3),centery+(shifty*3),size);
  var hex0_3draw = canvas.polygon(hex0_3.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_3draw);

  var hex0_4 = new Hexagon(centerx+(shiftx*4),centery+(shifty*4),size);
  var hex0_4draw = canvas.polygon(hex0_4.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_4draw);

  var hex0_5 = new Hexagon(centerx+(shiftx*5),centery+(shifty*5),size);
  var hex0_5draw = canvas.polygon(hex0_5.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_5draw);

  var hex0_6 = new Hexagon(centerx+(shiftx*6),centery+(shifty*6),size);
  var hex0_6draw = canvas.polygon(hex0_6.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_6draw);

  var hex0_7 = new Hexagon(centerx+(shiftx*7),centery+(shifty*7),size);
  var hex0_7draw = canvas.polygon(hex0_7.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_4draw);

  var hex0_8 = new Hexagon(centerx+(shiftx*8),centery+(shifty*8),size);
  var hex0_8draw = canvas.polygon(hex0_8.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_4draw);

  var hex0_9 = new Hexagon(centerx-(shiftx*9),centery-(shifty*9), size);
  var hex0_9draw = canvas.polygon(hex0_9.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex0_9draw);

  var hex9_9 = new Hexagon(centerx+(shiftx*9),centery-(shifty*9), size);
  var hex9_9draw = canvas.polygon(hex9_9.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex9_9draw);

  var hex90 = new Hexagon(centerx+(shiftx*18),centery, size);
  var hex90draw = canvas.polygon(hex90.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex90draw);

  var hex09 = new Hexagon(centerx+(shiftx*9),centery+(shifty*9), size);
  var hex09draw = canvas.polygon(hex09.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex09draw);

  var hex_99 = new Hexagon(centerx-(shiftx*9),centery+(shifty*9), size);
  var hex_99draw = canvas.polygon(hex_99.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex_99draw);

  var hex_90 = new Hexagon(centerx-(shiftx*18),centery, size);
  var hex_90draw = canvas.polygon(hex_90.path).fill('none').stroke({ width: 3 });
  griddraw.add(hex_90draw);

*/
});<|endoftext|>


<commit_before>
/**
 * Dependencies
 */

const actionCreators = require('./store/action-creators');
const SettingsScene = require('./views/settings-scene');
const notification = require('./notifications');
const ItemScene = require('./views/item-scene');
const ListScene = require('./views/list-scene');
const { bindActionCreators } = require('redux');
const ReactNative = require('react-native');
const { connect } = require('react-redux');
const track = require('./utils/tracker');
const debug = require('./debug')('App');
const { flags } = require('../config');
const Scanner = require('./scanner');
const React = require('react');

const {
  AsyncStorage,
  BackAndroid,
  Navigator,
  AppState,
  Platform,
  Linking,
  Alert,
} = ReactNative;

/**
 * The length of time we expect to
 * find nearby items in.
 *
 * If nothing is found in this time
 * period, we assume there's nothing
 * there.
 *
 * @type {Number}
 */
const INITIAL_SCAN_PERIOD = 8000; // 8 secs

/**
 * Main app view.
 *
 * Has no visual state, acts as 'container' for
 * app UI, composing components and supplying
 * them with the correct data.
 *
 * Uses `Navigator` to split the views into different 'scenes'.
 *
 * The parent `Provider` view passes the ReduxStore
 * `store`. We use 'react-redux' to expose *parts*
 * of this store to this view's `this.props.*`.
 *
 * @type {ReactComponent}
 */
class App extends React.Component {
  constructor(props) {
    super(props);

    // create the scanner
    this.scanner = new Scanner({
      onUpdate: this.props.updateItem,
      onLost: this.props.removeItem,
      onMetadata: this.props.setItemMetadata,
      expiryEnabled: this.enabled.bind(this, 'removeOldItems'),
      getItems: () => this.props.items
    });

    // we need to use telemetry after we
    // inflate the store with the user flags
    this.inflateUserFlags().then(() => {
      track.appLaunch();
      this.setupNotificationListeners();
    });

    // when network is bad, the scanner errors
    this.scanner.on('networkerror', this.onScannerNetworkError.bind(this));

    // respond to app background/foreground changes
    AppState.addEventListener('change', this.onAppStateChanged.bind(this));

    BackAndroid.addEventListener('hardwareBackPress', this.onAndroidBack.bind(this))
  }

  componentDidMount() {
    debug('mounted');
    this.startScanning();
  }

  /**
   * Triggered whenever the redux store updates.
   * We use this hook to channel the event to more
   * granular callbacks.
   */
  componentWillReceiveProps(next) {
    var current = this.props;
    if (next.userFlags !== current.userFlags) this.onUserFlagsChange(next.userFlags);
  }

  render() {
    return (
      <Navigator
        ref="navigator"
        initialRoute={{type: 'home'}}
        configureScene={() => Navigator.SceneConfigs.FloatFromBottom}
        onDidFocus={this.onNavigated.bind(this)}
        renderScene={this.renderScene.bind(this)}
      />
    );
  }

  /**
   * Called by `Navigator` to determin which
   * 'scene` gets rendered.
   */
  renderScene({ type }, navigator) {
    debug('render scene', type, this.props.openItem);

    switch (type) {
      case 'home': return <ListScene
        navigator={navigator}
        items={this.props.items}
        scanning={this.props.indicateScanning}
        onItemPress={this.onItemPress.bind(this)}
        onItemSwiped={this.onItemSwiped.bind(this)}
        userFlags={this.props.userFlags}
        onRefresh={this.onRefresh.bind(this)}/>
      case 'item':
      return <ItemScene
        navigator={navigator}
        item={this.props.openItem} />
      case 'settings': return <SettingsScene
        navigator={navigator}
        userFlags={this.props.userFlags}
        onSettingChange={this.props.setUserFlag}/>
    }
  }

  startScanning() {
    debug('start scanning');
    this.props.setIndicateScanning(true);
    this.scanner.start()
      .then(() => {
        debug('scanning started');
        clearTimeout(this.initialScanPeriodTimeout);
        this.initialScanPeriodTimeout = setTimeout(() => {
          this.props.setIndicateScanning(false);
        }, INITIAL_SCAN_PERIOD);
      })

      .catch(() => {
        debug('scanning failed to start');
        this.props.setIndicateScanning(false);
      });
  }

  stopScanning() {
    debug('stop scanning');
    this.scanner.stop();
    this.props.setIndicateScanning(false);
    debug('stopped', this.scanning);
  }

  /**
   * Check if the app was first launched from
   * a notification and listen for subsequent
   * launches.
   */
  setupNotificationListeners() {
    if (notification.launchedApp()) track.appOpenFromNotification();
    notification.on('applaunch', () => track.appLaunchFromNotification());
    notification.on('dismiss', () => track.notificationDismiss());
  }

  /**
   * When app boots the `userProps` state contains
   * only the default values. We have to fetch
   * the user's persisted values from an async
   * data-store. Once fetched we update or
   * 'inflate' the redux store with the
   * 'real' values.
   *
   * @return {Promise}
   */
  inflateUserFlags() {
    debug('inflate user flags');
    var flags = this.props.userFlags;

    return Promise.all(Object.keys(flags).map(key => {
      return AsyncStorage.getItem(`user-prefs:${key}`)
        .then(value => {
          debug('got user flag', key, value);
          value = parseBoolean(value);
          if (value == null) return;
          this.props.setUserFlag(key, value);
          debug('inflated user flag', key, value);
        });
    }));
  }

  /**
   * A convenient helper to check if a user-flag
   * is enabled or not.
   */
  enabled(key) {
    var flag = this.props.userFlags[key]
    return !flag ? true : flag.value;
  }

  /**
   * Called whenever the user changes a flag.
   *
   * We use this moment to persist their
   * chosen value to a data-store.
   *
   * @param {Object} nextUserFlags
   */
  onUserFlagsChange(nextUserFlags) {
    debug('on user flags change')
    this.persistUserFlags(nextUserFlags);
    track.enable(nextUserFlags.enableTelemetry.value);
  }

  persistUserFlags(flags) {
    Object.keys(flags).forEach(key => {
      var { value } = flags[key];
      AsyncStorage.setItem(`user-prefs:${key}`, String(value));
      debug('persisted user flag', key, value);
    });
  }

  /**
   * Called when the app moves to the
   * background or comes to the foreground.
   *
   * NOTE: This also fires when system dialogs
   * cover the app (eg. bluetooth prompt).
   *
   * @param {String} state
   */
  onAppStateChanged(state) {
    debug('app state changed', state);
    switch (state) {
      case 'active': return this.onForeground();
      case 'background': return this.onBackground();
    }
  }

  /**
   * Called when app comes to foreground.
   */
  onForeground() {
    track.appInForeground();
    this.startScanning();
  }

  /**
   * Called when app goes to background.
   *
   * We don't stop the scanner for iOS, as
   * we need the native scanner callback to
   * keep firing so that we can dispatch
   * notifications. In iOS there is no way
   * of spinning up background services
   * like in android.
   */
  onBackground() {
    track.appInBackground();
    if (!platform('ios')) {
      this.stopScanning();
    }
  }

  onScannerNetworkError() {
    debug('on network error');
    if (this.networkAlertOpen) return;
    this.networkAlertOpen = true;

    Alert.alert(
      'Network error',
      'Please check your internet connection',
      [{
        text: 'OK',
        onPress: this.onNetworkAlertClosed.bind(this)
      }]
    );
  }

  onNetworkAlertClosed() {
    setTimeout(() => this.networkAlertOpen = false, 500)
  }

  /**
   * Called when the user refreshes the list
   * via a pull-to-refresh gesture.
   */
  onRefresh() {
    debug('on refresh');
    track.pullRefresh();
    this.stopScanning();
    this.props.clearItems();
    this.startScanning();
  }

  /**
   * Called when the navigator finishes
   * a transition to a new 'scene'.
   */
  onNavigated({ type }) {
    debug('navigated', type);
    track.view(type);
  }

  /**
   * Called when a list-item is pressed.
   *
   * Depending on what prefs are set, this
   * could open the expanded view, or simply
   * navigate to the item's url.
   */
  onItemPress(item) {
    var url = item.metadata ? item.metadata.unadaptedUrl : item.url;
    track.tapListItem(url);
    if (!flags.itemsExpandable) return Linking.openURL(url);
    this.props.setOpenItem(item.id);
    this.refs.navigator.push({ type: 'item' });
  }

  onItemSwiped(item) {
    this.props.updateItem(item.id, { hidden: true });
  }

  /**
   * Responds to Android hardware back button.
   *
   * Returning `false` indicates the app
   * isn't handling the event and allows
   * the system to respond.
   *
   * @return {Boolean}
   */
  onAndroidBack() {
    debug('android back');
    var stack = this.refs.navigator.getCurrentRoutes();

    if (stack.length > 1) {
      this.refs.navigator.pop();
      return true;
    }

    // let system handle event
    // (minimises android app)
    return false;
  }
}

App.propTypes = {
  // actions
  setIndicateScanning: React.PropTypes.func,
  setOpenItem: React.PropTypes.func,
  setItemMetadata: React.PropTypes.func,
  setUserFlag: React.PropTypes.func,
  updateItem: React.PropTypes.func,
  removeItem: React.PropTypes.func,
  clearItems: React.PropTypes.func,

  // state
  indicateScanning: React.PropTypes.bool,
  userFlags: React.PropTypes.object,
  openItem: React.PropTypes.object,
  items: React.PropTypes.array,
}

/**
 * Takes the redux `store` (passed down by
 * the parent `Provider`) view and maps
 * specific properties onto the App's
 * `this.props` object.
 *
 * This means the app never touches the
 * redux store directly and prevents
 * hacky code being written.
 *
 * @param  {ReduxStore} store
 * @return {Object}
 */
function mapStateToProps(store) {
  return {
    indicateScanning: store.indicateScanning,
    userFlags: store.userFlags,
    openItem: store.openItem,
    items: store.items,
  };
}

/**
 * Maps the methods exported from `action-creators.js`
 * to `this.props.<ACTION_NAME>`.
 *
 * @param  {function} dispatch
 * @return {Object}
 */
function mapDispatchToProps(dispatch) {
  return bindActionCreators(actionCreators, dispatch);
}

/**
 * Exports
 */

module.exports = connect(mapStateToProps, mapDispatchToProps)(App);

/**
 * Utils
 */

function parseBoolean(value) {
  switch (value) {
    case 'true': return true;
    case 'false': return false;
    default: return null
  }
}

function platform(value) {
  return Platform.OS === value
}
<commit_msg>Fix typo, incorrect function name<commit_after>
/**
 * Dependencies
 */

const actionCreators = require('./store/action-creators');
const SettingsScene = require('./views/settings-scene');
const notification = require('./notifications');
const ItemScene = require('./views/item-scene');
const ListScene = require('./views/list-scene');
const { bindActionCreators } = require('redux');
const ReactNative = require('react-native');
const { connect } = require('react-redux');
const track = require('./utils/tracker');
const debug = require('./debug')('App');
const { flags } = require('../config');
const Scanner = require('./scanner');
const React = require('react');

const {
  AsyncStorage,
  BackAndroid,
  Navigator,
  AppState,
  Platform,
  Linking,
  Alert,
} = ReactNative;

/**
 * The length of time we expect to
 * find nearby items in.
 *
 * If nothing is found in this time
 * period, we assume there's nothing
 * there.
 *
 * @type {Number}
 */
const INITIAL_SCAN_PERIOD = 8000; // 8 secs

/**
 * Main app view.
 *
 * Has no visual state, acts as 'container' for
 * app UI, composing components and supplying
 * them with the correct data.
 *
 * Uses `Navigator` to split the views into different 'scenes'.
 *
 * The parent `Provider` view passes the ReduxStore
 * `store`. We use 'react-redux' to expose *parts*
 * of this store to this view's `this.props.*`.
 *
 * @type {ReactComponent}
 */
class App extends React.Component {
  constructor(props) {
    super(props);

    // create the scanner
    this.scanner = new Scanner({
      onUpdate: this.props.updateItem,
      onLost: this.props.removeItem,
      onMetadata: this.props.setItemMetadata,
      expiryEnabled: this.enabled.bind(this, 'removeOldItems'),
      getItems: () => this.props.items
    });

    // we need to use telemetry after we
    // inflate the store with the user flags
    this.inflateUserFlags().then(() => {
      track.appLaunch();
      this.setupNotificationListeners();
    });

    // when network is bad, the scanner errors
    this.scanner.on('networkerror', this.onScannerNetworkError.bind(this));

    // respond to app background/foreground changes
    AppState.addEventListener('change', this.onAppStateChanged.bind(this));

    BackAndroid.addEventListener('hardwareBackPress', this.onAndroidBack.bind(this))
  }

  componentDidMount() {
    debug('mounted');
    this.startScanning();
  }

  /**
   * Triggered whenever the redux store updates.
   * We use this hook to channel the event to more
   * granular callbacks.
   */
  componentWillReceiveProps(next) {
    var current = this.props;
    if (next.userFlags !== current.userFlags) this.onUserFlagsChange(next.userFlags);
  }

  render() {
    return (
      <Navigator
        ref="navigator"
        initialRoute={{type: 'home'}}
        configureScene={() => Navigator.SceneConfigs.FloatFromBottom}
        onDidFocus={this.onNavigated.bind(this)}
        renderScene={this.renderScene.bind(this)}
      />
    );
  }

  /**
   * Called by `Navigator` to determin which
   * 'scene` gets rendered.
   */
  renderScene({ type }, navigator) {
    debug('render scene', type, this.props.openItem);

    switch (type) {
      case 'home': return <ListScene
        navigator={navigator}
        items={this.props.items}
        scanning={this.props.indicateScanning}
        onItemPress={this.onItemPress.bind(this)}
        onItemSwiped={this.onItemSwiped.bind(this)}
        userFlags={this.props.userFlags}
        onRefresh={this.onRefresh.bind(this)}/>
      case 'item':
      return <ItemScene
        navigator={navigator}
        item={this.props.openItem} />
      case 'settings': return <SettingsScene
        navigator={navigator}
        userFlags={this.props.userFlags}
        onSettingChange={this.props.setUserFlag}/>
    }
  }

  startScanning() {
    debug('start scanning');
    this.props.setIndicateScanning(true);
    this.scanner.start()
      .then(() => {
        debug('scanning started');
        clearTimeout(this.initialScanPeriodTimeout);
        this.initialScanPeriodTimeout = setTimeout(() => {
          this.props.setIndicateScanning(false);
        }, INITIAL_SCAN_PERIOD);
      })

      .catch(() => {
        debug('scanning failed to start');
        this.props.setIndicateScanning(false);
      });
  }

  stopScanning() {
    debug('stop scanning');
    this.scanner.stop();
    this.props.setIndicateScanning(false);
    debug('stopped', this.scanning);
  }

  /**
   * Check if the app was first launched from
   * a notification and listen for subsequent
   * launches.
   */
  setupNotificationListeners() {
    if (notification.launchedApp()) track.appLaunchFromNotification();
    notification.on('applaunch', () => track.appLaunchFromNotification());
    notification.on('dismiss', () => track.notificationDismiss());
  }

  /**
   * When app boots the `userProps` state contains
   * only the default values. We have to fetch
   * the user's persisted values from an async
   * data-store. Once fetched we update or
   * 'inflate' the redux store with the
   * 'real' values.
   *
   * @return {Promise}
   */
  inflateUserFlags() {
    debug('inflate user flags');
    var flags = this.props.userFlags;

    return Promise.all(Object.keys(flags).map(key => {
      return AsyncStorage.getItem(`user-prefs:${key}`)
        .then(value => {
          debug('got user flag', key, value);
          value = parseBoolean(value);
          if (value == null) return;
          this.props.setUserFlag(key, value);
          debug('inflated user flag', key, value);
        });
    }));
  }

  /**
   * A convenient helper to check if a user-flag
   * is enabled or not.
   */
  enabled(key) {
    var flag = this.props.userFlags[key]
    return !flag ? true : flag.value;
  }

  /**
   * Called whenever the user changes a flag.
   *
   * We use this moment to persist their
   * chosen value to a data-store.
   *
   * @param {Object} nextUserFlags
   */
  onUserFlagsChange(nextUserFlags) {
    debug('on user flags change')
    this.persistUserFlags(nextUserFlags);
    track.enable(nextUserFlags.enableTelemetry.value);
  }

  persistUserFlags(flags) {
    Object.keys(flags).forEach(key => {
      var { value } = flags[key];
      AsyncStorage.setItem(`user-prefs:${key}`, String(value));
      debug('persisted user flag', key, value);
    });
  }

  /**
   * Called when the app moves to the
   * background or comes to the foreground.
   *
   * NOTE: This also fires when system dialogs
   * cover the app (eg. bluetooth prompt).
   *
   * @param {String} state
   */
  onAppStateChanged(state) {
    debug('app state changed', state);
    switch (state) {
      case 'active': return this.onForeground();
      case 'background': return this.onBackground();
    }
  }

  /**
   * Called when app comes to foreground.
   */
  onForeground() {
    track.appInForeground();
    this.startScanning();
  }

  /**
   * Called when app goes to background.
   *
   * We don't stop the scanner for iOS, as
   * we need the native scanner callback to
   * keep firing so that we can dispatch
   * notifications. In iOS there is no way
   * of spinning up background services
   * like in android.
   */
  onBackground() {
    track.appInBackground();
    if (!platform('ios')) {
      this.stopScanning();
    }
  }

  onScannerNetworkError() {
    debug('on network error');
    if (this.networkAlertOpen) return;
    this.networkAlertOpen = true;

    Alert.alert(
      'Network error',
      'Please check your internet connection',
      [{
        text: 'OK',
        onPress: this.onNetworkAlertClosed.bind(this)
      }]
    );
  }

  onNetworkAlertClosed() {
    setTimeout(() => this.networkAlertOpen = false, 500)
  }

  /**
   * Called when the user refreshes the list
   * via a pull-to-refresh gesture.
   */
  onRefresh() {
    debug('on refresh');
    track.pullRefresh();
    this.stopScanning();
    this.props.clearItems();
    this.startScanning();
  }

  /**
   * Called when the navigator finishes
   * a transition to a new 'scene'.
   */
  onNavigated({ type }) {
    debug('navigated', type);
    track.view(type);
  }

  /**
   * Called when a list-item is pressed.
   *
   * Depending on what prefs are set, this
   * could open the expanded view, or simply
   * navigate to the item's url.
   */
  onItemPress(item) {
    var url = item.metadata ? item.metadata.unadaptedUrl : item.url;
    track.tapListItem(url);
    if (!flags.itemsExpandable) return Linking.openURL(url);
    this.props.setOpenItem(item.id);
    this.refs.navigator.push({ type: 'item' });
  }

  onItemSwiped(item) {
    this.props.updateItem(item.id, { hidden: true });
  }

  /**
   * Responds to Android hardware back button.
   *
   * Returning `false` indicates the app
   * isn't handling the event and allows
   * the system to respond.
   *
   * @return {Boolean}
   */
  onAndroidBack() {
    debug('android back');
    var stack = this.refs.navigator.getCurrentRoutes();

    if (stack.length > 1) {
      this.refs.navigator.pop();
      return true;
    }

    // let system handle event
    // (minimises android app)
    return false;
  }
}

App.propTypes = {
  // actions
  setIndicateScanning: React.PropTypes.func,
  setOpenItem: React.PropTypes.func,
  setItemMetadata: React.PropTypes.func,
  setUserFlag: React.PropTypes.func,
  updateItem: React.PropTypes.func,
  removeItem: React.PropTypes.func,
  clearItems: React.PropTypes.func,

  // state
  indicateScanning: React.PropTypes.bool,
  userFlags: React.PropTypes.object,
  openItem: React.PropTypes.object,
  items: React.PropTypes.array,
}

/**
 * Takes the redux `store` (passed down by
 * the parent `Provider`) view and maps
 * specific properties onto the App's
 * `this.props` object.
 *
 * This means the app never touches the
 * redux store directly and prevents
 * hacky code being written.
 *
 * @param  {ReduxStore} store
 * @return {Object}
 */
function mapStateToProps(store) {
  return {
    indicateScanning: store.indicateScanning,
    userFlags: store.userFlags,
    openItem: store.openItem,
    items: store.items,
  };
}

/**
 * Maps the methods exported from `action-creators.js`
 * to `this.props.<ACTION_NAME>`.
 *
 * @param  {function} dispatch
 * @return {Object}
 */
function mapDispatchToProps(dispatch) {
  return bindActionCreators(actionCreators, dispatch);
}

/**
 * Exports
 */

module.exports = connect(mapStateToProps, mapDispatchToProps)(App);

/**
 * Utils
 */

function parseBoolean(value) {
  switch (value) {
    case 'true': return true;
    case 'false': return false;
    default: return null
  }
}

function platform(value) {
  return Platform.OS === value
}
<|endoftext|>


<commit_before>Package.describe({
  summary: 'Modular Application Architecture for Meteor.',
  name: 'space:base',
  version: '3.2.1',
  git: 'https://github.com/meteor-space/base.git'
});

Npm.depends({
  "getenv": "0.5.0",
  "winston": "2.1.0"
});

Package.onUse(function(api) {

  api.versionsFrom("METEOR@1.0");

  api.use([
    'coffeescript',
    'check',
    'underscore',
    'ecmascript'
  ]);

  api.use([
    'ejson',
    'ddp',
    'random',
    'mongo',
    'tracker',
    'templating',
    'session',
    'blaze',
    'email',
    'accounts-base',
    'reactive-var'
  ], {weak: true});

  api.addFiles([
    'source/lib/underscore_deep_extend_mixin.js',
    'source/namespace.coffee',
    'source/helpers.coffee',
    'source/configuration.js',
    'source/object.coffee',
    'source/logger.js',
    'source/struct.coffee',
    'source/error.js',
    'source/injector.coffee',
    'source/injector_annotations.coffee',
    'source/module.coffee',
    'source/application.coffee'
  ]);

});

Package.onTest(function(api) {

  api.use([
    'meteor',
    'coffeescript',
    'check',
    'ecmascript',
    'space:base',

    // weak-dependencies
    'ddp',
    'random',
    'underscore',
    'mongo',
    'tracker',
    'templating',
    'ejson',
    'accounts-base',
    'email',
    'session',
    'reactive-var',

    'grigio:babel@0.1.3',
    'practicalmeteor:munit@2.1.5',
    'space:testing@1.5.0'
  ]);

  api.addFiles([

    // unit tests
    'tests/unit/object.unit.coffee',
    'tests/unit/module.unit.coffee',
    'tests/unit/struct.unit.coffee',
    'tests/unit/application.unit.coffee',
    'tests/unit/injector.unit.coffee',
    'tests/unit/injector_annotations.unit.es6',
    'tests/unit/helpers.unit.coffee',
    'tests/unit/error.tests.js',
    'tests/unit/logger.tests.js',

    // integration tests
    'tests/integration/application_with_modules.spec.js',
    'tests/integration/standalone_application.integration.coffee',
    'tests/integration/lifecycle_hooks.tests.js',
    'tests/integration/requiring-modules.tests.js',
    'tests/integration/module.regressions.js'
  ]);

});
<commit_msg>Change package version to 0.7.0 and add documentation to package description<commit_after>Package.describe({
  summary: 'Modular Application Architecture for Meteor.',
  name: 'space:base',
  version: '0.7.0',
  git: 'https://github.com/meteor-space/base.git',
  documentation: 'README.md'
});

Npm.depends({
  "getenv": "0.5.0",
  "winston": "2.1.0"
});

Package.onUse(function(api) {

  api.versionsFrom("METEOR@1.0");

  api.use([
    'coffeescript',
    'check',
    'underscore',
    'ecmascript'
  ]);

  api.use([
    'ejson',
    'ddp',
    'random',
    'mongo',
    'tracker',
    'templating',
    'session',
    'blaze',
    'email',
    'accounts-base',
    'reactive-var'
  ], {weak: true});

  api.addFiles([
    'source/lib/underscore_deep_extend_mixin.js',
    'source/namespace.coffee',
    'source/helpers.coffee',
    'source/configuration.js',
    'source/object.coffee',
    'source/logger.js',
    'source/struct.coffee',
    'source/error.js',
    'source/injector.coffee',
    'source/injector_annotations.coffee',
    'source/module.coffee',
    'source/application.coffee'
  ]);

});

Package.onTest(function(api) {

  api.use([
    'meteor',
    'coffeescript',
    'check',
    'ecmascript',
    'space:base',

    // weak-dependencies
    'ddp',
    'random',
    'underscore',
    'mongo',
    'tracker',
    'templating',
    'ejson',
    'accounts-base',
    'email',
    'session',
    'reactive-var',

    'grigio:babel@0.1.3',
    'practicalmeteor:munit@2.1.5',
    'space:testing@1.5.0'
  ]);

  api.addFiles([

    // unit tests
    'tests/unit/object.unit.coffee',
    'tests/unit/module.unit.coffee',
    'tests/unit/struct.unit.coffee',
    'tests/unit/application.unit.coffee',
    'tests/unit/injector.unit.coffee',
    'tests/unit/injector_annotations.unit.es6',
    'tests/unit/helpers.unit.coffee',
    'tests/unit/error.tests.js',
    'tests/unit/logger.tests.js',

    // integration tests
    'tests/integration/application_with_modules.spec.js',
    'tests/integration/standalone_application.integration.coffee',
    'tests/integration/lifecycle_hooks.tests.js',
    'tests/integration/requiring-modules.tests.js',
    'tests/integration/module.regressions.js'
  ]);

});
<|endoftext|>


<commit_before>Package.describe({
  name: "sergeyt:dimple",
  summary: "dimple - an object-oriented API for business analytics powered by d3.",
  git: "https://github.com/sergeyt/meteor-dimple.git",
  version: "2.1.0"
});

Package.onUse(function(api){
  api.versionsFrom("METEOR@0.9.1");
  api.addFiles("dimple.js", "client");
});

<commit_msg>minor<commit_after>Package.describe({
  name: "sergeyt:dimple",
  summary: "dimple - an object-oriented API for business analytics powered by d3.",
  git: "https://github.com/sergeyt/meteor-dimple.git",
  version: "2.1.0"
});

Package.onUse(function(api){
  var client = ["client"];
  api.versionsFrom("METEOR@0.9.1");
  api.addFiles("dimple.js", client);
});

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Joyent, Inc.  All rights reserved.
 *
 * Firewall API server app
 */

var assert = require('assert-plus');
var clone = require('clone');
var endpoints = require('./endpoints');
var fs = require('fs');
var http = require('http');
var https = require('https');
var mod_update = require('./update');
var os = require('os');
var pipeline = require('./pipeline').pipeline;
var restify = require('restify');
var UFDS = require('sdc-clients').UFDS;
var verror = require('verror');
var VMAPI = require('sdc-clients').VMAPI;

// --- Globals

var VERSION = '0.0.2';

// --- FWAPI object and methods

/**
 * FWAPI Constructor
 */
function FWAPI(opts) {
    var self = this;

    assert.object(opts.config, 'opts.config');
    assert.object(opts.log, 'opts.log');

    this.config = opts.config;
    this.log = opts.log;

    var maxSockets = opts.config.maxHttpSockets || 100;
    opts.log.debug('Setting maxSockets to %d', maxSockets);
    http.globalAgent.maxSockets = maxSockets;
    https.globalAgent.maxSockets = maxSockets;

    // Runs before every request
    function setup(req, res, next) {
        req._app = self;
        req._ufds = self.ufds;
        req._vmapi = self.vmapi;
        req._update = self.updater;

        return next();
    }

    function checkServices(req, res, next) {
        var errs = [];
        if (!req._ufds) {
            errs.push({
                code: 'ServiceUnavailable',
                message: 'UFDS client not initialized'
            });
        }

        if (errs.length !== 0) {
            var err = new restify.ServiceUnavailableError(
                errs.length == 1 ? errs[0].message : 'Services unavailable');
            err.errors = errs;
            return next(err);
        }

        return next();
    }

    var server = this.server = restify.createServer({
        log: opts.log,
        name: 'SmartDC Firewall API',
        version: VERSION
    });
    server.use(restify.acceptParser(server.acceptable));
    server.use(restify.bodyParser());
    server.use(restify.queryParser());
    server.use(restify.requestLogger());
    server.use(function _headers(req, res, next) {
        res.on('header', function onHeader() {
            var now = Date.now();
            res.header('Date', new Date());
            res.header('Server', server.name);
            res.header('x-request-id', req.getId());
            var t = now - req.time();
            res.header('x-response-time', t);
            res.header('x-server-name', os.hostname());
        });

        return next();
    });

    var auditLog = restify.auditLogger({
        log: self.log.child({ component: 'audit' })
    });

    server.on('after', function _filteredAuditLog(req, res, route, err) {
        // Don't log ping requests, to avoid filling up the log
        if (route !== 'getping' && route !== 'headping') {
            auditLog(req, res, route, err);
        }
    });

    server.on('uncaughtException', function (req, res, route, err) {
        delete err.domain;
        req.log.error(err, 'Uncaught exception');
        res.send(new verror.WError(err, 'Internal error'));
    });

    endpoints.registerEndpoints(server, self.log, [setup, checkServices]);

    this.updater = mod_update.createServer({
        config: {
            host: os.hostname(),
            pollInterval: self.config.pollInterval,
            moray: self.config.moray,
            fast: self.config.fast
        },
        log: self.log
    });
}

/**
 * Close this app.
 *
 * @param {Function} callback called when closed. Takes no arguments.
 */
FWAPI.prototype.close = function close(callback) {
    var self = this;
    this.server.on('close', function () {
        self.ufds.close(function (err) {
            if (err) {
                self.log.error(err, 'Error closing UFDS connection');
            }

            return callback();
        });
    });

    this.server.close();
    this.updater.close();
};

/**
 * Starts the server
 */
FWAPI.prototype.listen = function listen(callback) {
    this.server.listen(this.config.port, callback);

    if (!this.ufds) {
        this.ufdsClientInit();
    }

    if (!this.vmapi) {
        this.vmapiClientInit();
    }

    this.updater.init();
};

/**
 * Return server information
 */
FWAPI.prototype.info = function info() {
    var addr = this.server.address();
    addr.name = this.server.name;
    addr.url = this.server.url;

    return addr;
};

/**
 * Creates the UFDS client
 */
FWAPI.prototype.ufdsClientInit = function ufdsClientInit() {
    var self = this;
    var att = 1;
    var conf = clone(this.config.ufds);
    var timeout = null;

    conf.log = this.log;

    function initUFDSretry() {
        self.log.debug('Initializing UFDS client: attempt %d', att);

        var client = new UFDS(conf);
        client.once('error', function (e) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }

            self.log.error(e,
                'Error connecting to UFDS (attempt: %d): retrying', att);
            att++;
            timeout = setTimeout(initUFDSretry, 10000);
        });

        client.once('connect', function () {
            client.removeAllListeners('error');

            function _onClose(err) {
                self.log.error(err, 'UFDS disconnected');
                client._connected = false;
            }
            client.on('error', _onClose);
            client.on('close', _onClose);

            client.on('connect', function (err) {
                self.log.error(err, 'UFDS reconnected');
                client._connected = true;
            });

            self.log.info('UFDS client ready');
            client._connected = true;
            self.ufds = client;
        });
    }

    initUFDSretry();
};

/**
 * Creates the VMAPI client
 */
FWAPI.prototype.vmapiClientInit = function vmapiClientInit() {
    var self = this;
    var conf = clone(this.config.vmapi);
    conf.log = self.log.child({ component: 'vmapiClient', level: 'trace' });

    // XXX: retry here, calling /ping?
    self.vmapi = new VMAPI(conf);
};

// --- Exports

/**
 * Create the app.
 *
 * @param opts {Object} Options:
 * - `config` {Object}: config (required)
 * - `log` {Object}: bunyan logger (required)
 * @param callback {Function} `function (err, app) {...}`.
 */
function createApp(opts, callback) {
    assert.object(opts, 'opts');
    assert.object(opts.config, 'opts.config');
    assert.object(opts.config.ufds, 'opts.config.ufds');
    assert.number(opts.config.port, 'opts.config.port');

    assert.object(opts.log, 'opts.log');

    return new FWAPI({
        config: opts.config,
        log: opts.log
    });
}

module.exports = {
    create: createApp
};
<commit_msg>FWAPI-174: Not logging the rule for creation errors<commit_after>/*
 * Copyright (c) 2014 Joyent, Inc.  All rights reserved.
 *
 * Firewall API server app
 */

var assert = require('assert-plus');
var clone = require('clone');
var endpoints = require('./endpoints');
var fs = require('fs');
var http = require('http');
var https = require('https');
var mod_update = require('./update');
var os = require('os');
var pipeline = require('./pipeline').pipeline;
var restify = require('restify');
var UFDS = require('sdc-clients').UFDS;
var verror = require('verror');
var VMAPI = require('sdc-clients').VMAPI;

// --- Globals

var VERSION = '0.0.2';

// --- FWAPI object and methods

/**
 * FWAPI Constructor
 */
function FWAPI(opts) {
    var self = this;

    assert.object(opts.config, 'opts.config');
    assert.object(opts.log, 'opts.log');

    this.config = opts.config;
    this.log = opts.log;

    var maxSockets = opts.config.maxHttpSockets || 100;
    opts.log.debug('Setting maxSockets to %d', maxSockets);
    http.globalAgent.maxSockets = maxSockets;
    https.globalAgent.maxSockets = maxSockets;

    // Runs before every request
    function setup(req, res, next) {
        req._app = self;
        req._ufds = self.ufds;
        req._vmapi = self.vmapi;
        req._update = self.updater;

        return next();
    }

    function checkServices(req, res, next) {
        var errs = [];
        if (!req._ufds) {
            errs.push({
                code: 'ServiceUnavailable',
                message: 'UFDS client not initialized'
            });
        }

        if (errs.length !== 0) {
            var err = new restify.ServiceUnavailableError(
                errs.length == 1 ? errs[0].message : 'Services unavailable');
            err.errors = errs;
            return next(err);
        }

        return next();
    }

    var server = this.server = restify.createServer({
        log: opts.log,
        name: 'SmartDC Firewall API',
        version: VERSION
    });
    server.use(restify.acceptParser(server.acceptable));
    server.use(restify.bodyParser());
    server.use(restify.queryParser());
    server.use(restify.requestLogger());
    server.use(function _headers(req, res, next) {
        res.on('header', function onHeader() {
            var now = Date.now();
            res.header('Date', new Date());
            res.header('Server', server.name);
            res.header('x-request-id', req.getId());
            var t = now - req.time();
            res.header('x-response-time', t);
            res.header('x-server-name', os.hostname());
        });

        return next();
    });

    server.on('after', function _filteredAuditLog(req, res, route, err) {
        // Don't log ping requests, to avoid filling up the log
        if (route && (route.name == 'getping' || route.name == 'headping')) {
            return;
        }

        restify.auditLogger({
            log: req.log.child({
                component: 'audit',
                route: route && route.name
            }, true),
            // Successful GET res bodies are uninteresting and *big*.
            body: !((req.method === 'GET') &&
                Math.floor(res.statusCode/100) === 2)
        })(req, res, route, err);
    });

    server.on('uncaughtException', function (req, res, route, err) {
        delete err.domain;
        req.log.error(err, 'Uncaught exception');
        res.send(new verror.WError(err, 'Internal error'));
    });

    endpoints.registerEndpoints(server, self.log, [setup, checkServices]);

    this.updater = mod_update.createServer({
        config: {
            host: os.hostname(),
            pollInterval: self.config.pollInterval,
            moray: self.config.moray,
            fast: self.config.fast
        },
        log: self.log
    });
}

/**
 * Close this app.
 *
 * @param {Function} callback called when closed. Takes no arguments.
 */
FWAPI.prototype.close = function close(callback) {
    var self = this;
    this.server.on('close', function () {
        self.ufds.close(function (err) {
            if (err) {
                self.log.error(err, 'Error closing UFDS connection');
            }

            return callback();
        });
    });

    this.server.close();
    this.updater.close();
};

/**
 * Starts the server
 */
FWAPI.prototype.listen = function listen(callback) {
    this.server.listen(this.config.port, callback);

    if (!this.ufds) {
        this.ufdsClientInit();
    }

    if (!this.vmapi) {
        this.vmapiClientInit();
    }

    this.updater.init();
};

/**
 * Return server information
 */
FWAPI.prototype.info = function info() {
    var addr = this.server.address();
    addr.name = this.server.name;
    addr.url = this.server.url;

    return addr;
};

/**
 * Creates the UFDS client
 */
FWAPI.prototype.ufdsClientInit = function ufdsClientInit() {
    var self = this;
    var att = 1;
    var conf = clone(this.config.ufds);
    var timeout = null;

    conf.log = this.log;

    function initUFDSretry() {
        self.log.debug('Initializing UFDS client: attempt %d', att);

        var client = new UFDS(conf);
        client.once('error', function (e) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }

            self.log.error(e,
                'Error connecting to UFDS (attempt: %d): retrying', att);
            att++;
            timeout = setTimeout(initUFDSretry, 10000);
        });

        client.once('connect', function () {
            client.removeAllListeners('error');

            function _onClose(err) {
                self.log.error(err, 'UFDS disconnected');
                client._connected = false;
            }
            client.on('error', _onClose);
            client.on('close', _onClose);

            client.on('connect', function (err) {
                self.log.error(err, 'UFDS reconnected');
                client._connected = true;
            });

            self.log.info('UFDS client ready');
            client._connected = true;
            self.ufds = client;
        });
    }

    initUFDSretry();
};

/**
 * Creates the VMAPI client
 */
FWAPI.prototype.vmapiClientInit = function vmapiClientInit() {
    var self = this;
    var conf = clone(this.config.vmapi);
    conf.log = self.log.child({ component: 'vmapiClient', level: 'trace' });

    // XXX: retry here, calling /ping?
    self.vmapi = new VMAPI(conf);
};

// --- Exports

/**
 * Create the app.
 *
 * @param opts {Object} Options:
 * - `config` {Object}: config (required)
 * - `log` {Object}: bunyan logger (required)
 * @param callback {Function} `function (err, app) {...}`.
 */
function createApp(opts, callback) {
    assert.object(opts, 'opts');
    assert.object(opts.config, 'opts.config');
    assert.object(opts.config.ufds, 'opts.config.ufds');
    assert.number(opts.config.port, 'opts.config.port');

    assert.object(opts.log, 'opts.log');

    return new FWAPI({
        config: opts.config,
        log: opts.log
    });
}

module.exports = {
    create: createApp
};
<|endoftext|>


<commit_before>Package.describe({
  name: "yogiben:autoform-file",
  summary: "File upload for AutoForm",
  description: "File upload for AutoForm",
  version: "0.2.7",
  git: "http://github.com/yogiben/autoform-file.git"
});

Package.onUse(function(api) {
  api.versionsFrom('METEOR@1.0');

  api.use([
    'coffeescript',
    'underscore',
    'reactive-var',
    'templating',
    'less',
    'aldeed:autoform@5.3.0',
    'fortawesome:fontawesome@4.3.0'
  ]);

  api.addFiles('lib/client/autoform-file.html', 'client');
  api.addFiles('lib/client/autoform-file.less', 'client');
  api.addFiles('lib/client/autoform-file.coffee', 'client');
  api.addFiles('lib/server/publish.coffee', 'server');
});
<commit_msg>Update deps. Bump version<commit_after>Package.describe({
  name: "yogiben:autoform-file",
  summary: "File upload for AutoForm",
  description: "File upload for AutoForm",
  version: "0.2.8",
  git: "http://github.com/yogiben/autoform-file.git"
});

Package.onUse(function(api) {
  api.versionsFrom('METEOR@1.0');

  api.use([
    'coffeescript',
    'underscore',
    'reactive-var',
    'templating',
    'less',
    'aldeed:autoform@5.3.2',
    'fortawesome:fontawesome@4.3.0'
  ]);

  api.addFiles('lib/client/autoform-file.html', 'client');
  api.addFiles('lib/client/autoform-file.less', 'client');
  api.addFiles('lib/client/autoform-file.coffee', 'client');
  api.addFiles('lib/server/publish.coffee', 'server');
});
<|endoftext|>


<commit_before>var autoplay = null;

function Autoplay() {
    return {
    	// Attributes
    	lastGameState: null,
    	movementsCounter: 0,
    	movements: {
    		UP: 38,
    		DOWN: 40,
    		LEFT: 37,
    		RIGHT: 39
    	},
    	isEqualState: function(gameState1, gameState2) {
    		if(gameState1 == null || gameState2 == null) return false;
    		var cells1 = gameState1.grid.cells;
    		var cells2 = gameState2.grid.cells;
    		for(var i=0; i<4; i++) {
    			for(var j=0; j<4; j++) {
    				if(cells1[i][j] != null && cells2[i][j] != null) {
    					if(cells1[i][j].value != cells2[i][j].value)
    						return false;
    				} else if((cells1[i][j] == null && cells2[i][j] != null) || (cells1[i][j] != null && cells2[i][j] == null)) {
    					return false;
    				}
    			}
    		}
    		return true;
    	},
    	// Methods
        selectMovement: function() {
        	var gameState = $.parseJSON(localStorage.gameState);
        	var vertical = 3, horizontal = 3;
        	var verticalTest = 2, horizontalTest = 2;
        	while(true) {
        		// Set pivot
    			var downCell = gameState.grid.cells[horizontal][vertical];
    			var downValue = downCell != null ? downCell.value : null;
    			if(downCell == null) {
    				vertical--;
    				if(vertical > 1) {
    					verticalTest = vertical - 1;
    					continue;
    				}
    				return this.movements.RIGHT;
    			} else {
    				// Down cell was defined. Search up cell.
    				var upCell = gameState.grid.cells[horizontal][verticalTest];
    				var upValue = upCell != null ? upCell.value : null;
    				if(upCell == null) {
    					verticalTest--;
    					if(verticalTest >= 0) continue;
    					return this.movements.RIGHT;
    				}
    				// Up cell was defined. Test in vertical for down movements
    				if(upValue == downValue) return this.movements.DOWN;
    				else return this.movements.RIGHT;
    			}
        	}
        },
        triggerKeyevent: function(keyCode) {
            var eventObject = document.createEventObject ? document.createEventObject() : document.createEvent("Events");
            if(eventObject.initEvent) eventObject.initEvent('keydown', true, true); // for createEvent method
            eventObject.keyCode = keyCode;
            eventObject.which = keyCode;
            document.body.dispatchEvent ? document.body.dispatchEvent(eventObject) : document.body.fireEvent('onkeydown', eventObject); // for old browsers
        },
        run: function() {
        	console.log(this.movementsCounter++);
    		var movement = this.selectMovement();
    		this.triggerKeyevent(movement);
    		var gameState = $.parseJSON(localStorage.gameState);
    		if(this.isEqualState(this.lastGameState, gameState)) return;
    		console.log('son distintos');
    		this.lastGameState = gameState;
    		setTimeout(function() { autoplay.run(); }, 500);
        }
    }
}

$(document).ready(function() {

	$('.autoplay-button').click(function() {
		autoplay = new Autoplay();
		autoplay.run();
	});

});<commit_msg>minor fixes<commit_after>var autoplay = null;

function Autoplay() {
    return {
    	// Attributes
    	lastGameState: null,
    	movementsCounter: 0,
    	movements: {
    		UP: 38,
    		DOWN: 40,
    		LEFT: 37,
    		RIGHT: 39
    	},
        // Methods
    	isEqualState: function(gameState1, gameState2) {
    		if(gameState1 == null || gameState2 == null) return false;
    		var cells1 = gameState1.grid.cells;
    		var cells2 = gameState2.grid.cells;
    		for(var i=0; i<4; i++) {
    			for(var j=0; j<4; j++) {
    				if(cells1[i][j] != null && cells2[i][j] != null) {
    					if(cells1[i][j].value != cells2[i][j].value)
    						return false;
    				} else if((cells1[i][j] == null && cells2[i][j] != null) || (cells1[i][j] != null && cells2[i][j] == null)) {
    					return false;
    				}
    			}
    		}
    		return true;
    	},
        selectMovement: function() {
        	var gameState = $.parseJSON(localStorage.gameState);
        	var vertical = 3, horizontal = 3;
        	var verticalTest = 2, horizontalTest = 2;
        	while(true) {
        		// Set pivot
    			var downCell = gameState.grid.cells[horizontal][vertical];
    			var downValue = downCell != null ? downCell.value : null;
    			if(downCell == null) {
    				vertical--;
    				if(vertical > 1) {
    					verticalTest = vertical - 1;
    					continue;
    				}
    				return this.movements.RIGHT;
    			} else {
    				// Down cell was defined. Search up cell.
    				var upCell = gameState.grid.cells[horizontal][verticalTest];
    				var upValue = upCell != null ? upCell.value : null;
    				if(upCell == null) {
    					verticalTest--;
    					if(verticalTest >= 0) continue;
    					return this.movements.RIGHT;
    				}
    				// Up cell was defined. Test in vertical for down movements
    				if(upValue == downValue) return this.movements.DOWN;
    				else return this.movements.RIGHT;
    			}
        	}
        },
        triggerKeyevent: function(keyCode) {
            var eventObject = document.createEventObject ? document.createEventObject() : document.createEvent("Events");
            if(eventObject.initEvent) eventObject.initEvent('keydown', true, true); // for createEvent method
            eventObject.keyCode = keyCode;
            eventObject.which = keyCode;
            document.body.dispatchEvent ? document.body.dispatchEvent(eventObject) : document.body.fireEvent('onkeydown', eventObject); // for old browsers
        },
        run: function() {
        	console.log('Cantidad de movimientos: ' + this.movementsCounter++);
    		var movement = this.selectMovement();
    		this.triggerKeyevent(movement);
    		var gameState = $.parseJSON(localStorage.gameState);
    		if(this.isEqualState(this.lastGameState, gameState)) return;
    		this.lastGameState = gameState;
    		setTimeout(function() { autoplay.run(); }, 500);
        }
    }
}

$(document).ready(function() {

	$('.autoplay-button').click(function() {
		autoplay = new Autoplay();
		autoplay.run();
	});

});<|endoftext|>


<commit_before>// Meteor package definition.
Package.describe({
  name: 'aramk:vega-charts',
  version: '0.1.0',
  summary: 'Simple charting with Vega and D3.',
  git: 'https://github.com/aramk/vega-charts.git'
});

Package.onUse(function (api) {
  api.versionsFrom('METEOR@0.9.0');
  api.use([
    'coffeescript',
    'jquery',
    'less',
    'templating',
    'underscore',
    'aramk:q@1.0.1',
    'aramk:utility@0.3.0',
    'aramk:vega@1.4.2'
    ],'client');
  api.imply('aramk:vega');
  // TODO(aramk) Perhaps expose the charts through the Vega object only to avoid cluttering the
  // namespace.
  api.export([
    'Vega', 'PieChart'
  ], 'client');
  api.addFiles([
    'src/Vega.coffee',
    'src/PieChart.coffee',
    'src/chart.less',
    'src/meteor/pieChart.html',
    'src/meteor/pieChart.coffee',
  ], 'client');
});
<commit_msg>Version bump.<commit_after>// Meteor package definition.
Package.describe({
  name: 'aramk:vega-charts',
  version: '0.2.0',
  summary: 'Simple charting with Vega and D3.',
  git: 'https://github.com/aramk/vega-charts.git'
});

Package.onUse(function (api) {
  api.versionsFrom('METEOR@0.9.0');
  api.use([
    'coffeescript',
    'jquery',
    'less',
    'templating',
    'underscore',
    'aramk:q@1.0.1',
    'aramk:utility@0.3.0',
    'aramk:vega@1.4.2'
    ],'client');
  api.imply('aramk:vega');
  // TODO(aramk) Perhaps expose the charts through the Vega object only to avoid cluttering the
  // namespace.
  api.export([
    'Vega', 'PieChart'
  ], 'client');
  api.addFiles([
    'src/Vega.coffee',
    'src/PieChart.coffee',
    'src/chart.less',
    'src/meteor/pieChart.html',
    'src/meteor/pieChart.coffee',
  ], 'client');
});
<|endoftext|>


<commit_before><commit_msg>fix(bestiary) alphabetise filter<commit_after><|endoftext|>


<commit_before>function trelloCalendarApp(config) {
    var express = require('express');
    var Seq = require('seq');
    var generateIcal = require('./calendar').generateIcal;
    var _ = require('underscore');

    var app = express.createServer();

    app.set('view engine', 'jade');
    app.set('views', __dirname + '/views');

    app.use(express.static(__dirname + '/../public'));
    app.use(require('connect-assets')({src: __dirname +'/../assets'}));

    /**
     * Index page
     */
    app.get('/', function(req, res) {
        if (req.trello) {
            app.emit('rootLogged');
            res.render('index_logged', {logged: true, uuid: req.session.uuid, config: config});
        } else {
            app.emit('rootUnlogged');
            res.render('index_unlogged', {logged: false, https: req.protocol == 'https', config: config});
        }
    });

    /**
     * Trello proxy
     * We don't want to expose all operations, except read one
     */
    app.get(/\/trello\/(.+)/, function(req, res) {
        if (!req.trello) return res.send("no session", 401);
        req.trello.get('/'+ req.params[0], req.query, function(err, data) {
            if (err) return res.send("error", 500);
            app.emit('trelloApiGet');
            res.json(data);
        });
    });

    /**
     * Only allow update due date on a card
     */
    app.put(/\/trello\/cards\/(.+)/, function(req, res) {
        if (!req.trello) return res.send("no session", 401);
        req.trello.put('/cards/'+ req.params[0], {due: req.body.badges.due}, function(err, data) {
            if (err) return res.send("error", 500);
            app.emit('trelloApiPut');
            res.json(data);
        });
    });

    app.param('uuid', function(req, res, next, uuid) {
        var trello = require('trello_baseapp/lib/trello')(config.trello.key, config.trello.secret);
        trello.buildFor(uuid, req, next);
    });

    /**
     * Return the calendar of all boards for the current token
     */
    app.get('/calendar/:uuid/all.ics', function(req, res) {
        function error(e) {
            res.send("error", 500);
        }
        if (!req.trello) return error();

        app.emit('calendarAll');
        app.emit('calendar');

        var models = req.trello;

        function fetchCardsAndGenerate(boards) {
            var seq = new Seq(boards.models).parEach(function(board) {
                var self = this;
                board.cards().fetch({
                    success: function() { self(); },
                    error: error
                });
            }).seq(function() {
                res.charset = 'utf8';
                res.contentType('ics');
                res.send(generateIcal(currentUser, boards, req.query).toString());
            });
        }

        function fetchBoards() {
            var boards = new models.Boards();
            boards.fetch({
                success: fetchCardsAndGenerate,
                error: error
            });
        }

        var currentUser = new models.CurrentUser();
        currentUser.fetch({
            success: fetchBoards,
            error: error
        });
    });

    /**
     * Return the calendar for a board
     */
    app.get('/calendar/:uuid/board/:board/:name.ics', function(req, res) {
        function error(e) {
            res.send("error", 500);
        }
        if (!req.trello) return error();

        app.emit('calendarBoard');
        app.emit('calendar');

        var models = req.trello;

        function fetchCardsAndGenerate() {
            var board = new models.Board({id: req.params.board})
            board.cards().fetch({
                success: function() {
                    res.charset = 'utf8';
                    res.contentType('ics');
                    res.send(generateIcal(currentUser, _([board]), req.query).toString());
                },
                error: error
            });
        }

        var currentUser = new models.CurrentUser();
        currentUser.fetch({
            success: fetchCardsAndGenerate,
            error: error
        });
    });

    return app;
}

module.exports = trelloCalendarApp;
<commit_msg>Use function.bind instead of self for the callback.<commit_after>function trelloCalendarApp(config) {
    var express = require('express');
    var Seq = require('seq');
    var generateIcal = require('./calendar').generateIcal;
    var _ = require('underscore');

    var app = express.createServer();

    app.set('view engine', 'jade');
    app.set('views', __dirname + '/views');

    app.use(express.static(__dirname + '/../public'));
    app.use(require('connect-assets')({src: __dirname +'/../assets'}));

    /**
     * Index page
     */
    app.get('/', function(req, res) {
        if (req.trello) {
            app.emit('rootLogged');
            res.render('index_logged', {logged: true, uuid: req.session.uuid, config: config});
        } else {
            app.emit('rootUnlogged');
            res.render('index_unlogged', {logged: false, https: req.protocol == 'https', config: config});
        }
    });

    /**
     * Trello proxy
     * We don't want to expose all operations, except read one
     */
    app.get(/\/trello\/(.+)/, function(req, res) {
        if (!req.trello) return res.send("no session", 401);
        req.trello.get('/'+ req.params[0], req.query, function(err, data) {
            if (err) return res.send("error", 500);
            app.emit('trelloApiGet');
            res.json(data);
        });
    });

    /**
     * Only allow update due date on a card
     */
    app.put(/\/trello\/cards\/(.+)/, function(req, res) {
        if (!req.trello) return res.send("no session", 401);
        req.trello.put('/cards/'+ req.params[0], {due: req.body.badges.due}, function(err, data) {
            if (err) return res.send("error", 500);
            app.emit('trelloApiPut');
            res.json(data);
        });
    });

    app.param('uuid', function(req, res, next, uuid) {
        var trello = require('trello_baseapp/lib/trello')(config.trello.key, config.trello.secret);
        trello.buildFor(uuid, req, next);
    });

    /**
     * Return the calendar of all boards for the current token
     */
    app.get('/calendar/:uuid/all.ics', function(req, res) {
        function error(e) {
            res.send("error", 500);
        }
        if (!req.trello) return error();

        app.emit('calendarAll');
        app.emit('calendar');

        var models = req.trello;

        function fetchCardsAndGenerate(boards) {
            var seq = new Seq(boards.models).parEach(function(board) {
                board.cards().fetch({
                    success: function() { this(); }.bind(this),
                    error: error
                });
            }).seq(function() {
                res.charset = 'utf8';
                res.contentType('ics');
                res.send(generateIcal(currentUser, boards, req.query).toString());
            });
        }

        function fetchBoards() {
            var boards = new models.Boards();
            boards.fetch({
                success: fetchCardsAndGenerate,
                error: error
            });
        }

        var currentUser = new models.CurrentUser();
        currentUser.fetch({
            success: fetchBoards,
            error: error
        });
    });

    /**
     * Return the calendar for a board
     */
    app.get('/calendar/:uuid/board/:board/:name.ics', function(req, res) {
        function error(e) {
            res.send("error", 500);
        }
        if (!req.trello) return error();

        app.emit('calendarBoard');
        app.emit('calendar');

        var models = req.trello;

        function fetchCardsAndGenerate() {
            var board = new models.Board({id: req.params.board})
            board.cards().fetch({
                success: function() {
                    res.charset = 'utf8';
                    res.contentType('ics');
                    res.send(generateIcal(currentUser, _([board]), req.query).toString());
                },
                error: error
            });
        }

        var currentUser = new models.CurrentUser();
        currentUser.fetch({
            success: fetchCardsAndGenerate,
            error: error
        });
    });

    return app;
}

module.exports = trelloCalendarApp;
<|endoftext|>


<commit_before>Package.describe({
  "summary": "Performance Monitoring for Meteor",
  "version": "2.20.4",
  "git": "https://github.com/meteorhacks/kadira.git",
  "name": "meteorhacks:kadira"
});

var npmModules = {
  "debug": "0.7.4",
  "request": "2.51.0",
  "pidusage": "0.1.1"
};

Npm.depends(npmModules);

Package.on_use(function(api) {
  configurePackage(api);
  api.export(['Kadira']);
});

Package.on_test(function(api) {
  configurePackage(api);
  api.use([
    'tinytest',
    'test-helpers'
  ], ['client', 'server']);

  // common before
  api.add_files([
    'tests/models/base_error.js'
  ], ['client', 'server']);

  // common server
  api.add_files([
    'tests/utils.js',
    'tests/ntp.js',
    'tests/jobs.js',
    'tests/_helpers/globals.js',
    'tests/_helpers/helpers.js',
    'tests/_helpers/init.js',
    'tests/ping.js',
    'tests/hijack/info.js',
    'tests/hijack/user.js',
    'tests/hijack/email.js',
    'tests/hijack/base.js',
    'tests/hijack/async.js',
    'tests/hijack/http.js',
    'tests/hijack/db.js',
    'tests/hijack/subscriptions.js',
    'tests/hijack/error.js',
    'tests/models/methods.js',
    'tests/models/pubsub.js',
    'tests/models/system.js',
    'tests/models/errors.js',
    'tests/tracer/tracer_store.js',
    'tests/tracer/tracer.js',
    'tests/tracer/default_filters.js',
    'tests/check_for_oplog.js',
    'tests/error_tracking.js',
    'tests/wait_time_builder.js',
    'tests/hijack/set_labels.js',
    'tests/environment_variables.js',
  ], 'server');

  // common client
  api.add_files([
    'tests/client/utils.js',
    'tests/client/error_tracking.js',
    'tests/client/models/error.js',
    'tests/client/error_reporters/window_error.js',
    'tests/client/error_reporters/zone.js',
    'tests/client/error_reporters/meteor_debug.js',
  ], 'client');

  // common after
  api.add_files([
    'tests/common/default_error_filters.js',
    'tests/common/send.js'
  ], ['client', 'server']);
});

function configurePackage(api) {
  if(api.versionsFrom) {
    api.versionsFrom('METEOR@0.9.1');
    api.use('meteorhacks:meteorx@1.3.1');
    api.use('meteorhacks:zones@1.2.1', {weak: true});
  } else {
    // for Meteor releases <= 0.8.3
    // now, zones is a weak dependancy!
    // kadira on the client side knows how to handle it
    // api.use('zones');
    api.use('meteorx');
  }

  api.use([
    'minimongo', 'livedata', 'mongo-livedata', 'ejson',
    'underscore', 'http', 'email', 'random'
  ], ['server']);
  api.use(['underscore', 'random', 'jquery', 'localstorage'], ['client']);

  // common before
  api.add_files([
    'lib/common/unify.js',
    'lib/models/base_error.js'
  ], ['client', 'server']);

  // only server
  api.add_files([
    'lib/jobs.js',
    'lib/retry.js',
    'lib/utils.js',
    'lib/ntp.js',
    'lib/wait_time_builder.js',
    'lib/models/0model.js',
    'lib/models/methods.js',
    'lib/models/pubsub.js',
    'lib/models/system.js',
    'lib/models/errors.js',
    'lib/kadira.js',
    'lib/check_for_oplog.js',
    'lib/tracer/tracer.js',
    'lib/tracer/default_filters.js',
    'lib/tracer/tracer_store.js',
    'lib/hijack/wrap_server.js',
    'lib/hijack/wrap_session.js',
    'lib/hijack/wrap_subscription.js',
    'lib/hijack/wrap_observers.js',
    'lib/hijack/session.js',
    'lib/hijack/db.js',
    'lib/hijack/http.js',
    'lib/hijack/email.js',
    'lib/hijack/async.js',
    'lib/hijack/error.js',
    'lib/hijack/set_labels.js',
    'lib/environment_variables.js',
    'lib/auto_connect.js'
  ], 'server');

  // only client
  api.add_files([
    'lib/retry.js',
    'lib/ntp.js',
    'lib/client/utils.js',
    'lib/client/models/error.js',
    'lib/client/error_reporters/zone.js',
    'lib/client/error_reporters/window_error.js',
    'lib/client/error_reporters/meteor_debug.js',
    'lib/client/kadira.js'
  ], 'client');

  api.add_files([
    // It's possible to remove this file after some since this just contains
    // a notice to the user.
    // Actual implementation is in the meteorhacks:kadira-profiler package
    'lib/profiler/client.js',
  ], 'client');

  // common after
  api.add_files([
    'lib/common/default_error_filters.js',
    'lib/common/send.js'
  ], ['client', 'server']);
}
<commit_msg>Bump versions<commit_after>Package.describe({
  "summary": "Performance Monitoring for Meteor",
  "version": "2.20.5",
  "git": "https://github.com/meteorhacks/kadira.git",
  "name": "meteorhacks:kadira"
});

var npmModules = {
  "debug": "0.7.4",
  "request": "2.51.0",
  "pidusage": "0.1.1"
};

Npm.depends(npmModules);

Package.on_use(function(api) {
  configurePackage(api);
  api.export(['Kadira']);
});

Package.on_test(function(api) {
  configurePackage(api);
  api.use([
    'tinytest',
    'test-helpers'
  ], ['client', 'server']);

  // common before
  api.add_files([
    'tests/models/base_error.js'
  ], ['client', 'server']);

  // common server
  api.add_files([
    'tests/utils.js',
    'tests/ntp.js',
    'tests/jobs.js',
    'tests/_helpers/globals.js',
    'tests/_helpers/helpers.js',
    'tests/_helpers/init.js',
    'tests/ping.js',
    'tests/hijack/info.js',
    'tests/hijack/user.js',
    'tests/hijack/email.js',
    'tests/hijack/base.js',
    'tests/hijack/async.js',
    'tests/hijack/http.js',
    'tests/hijack/db.js',
    'tests/hijack/subscriptions.js',
    'tests/hijack/error.js',
    'tests/models/methods.js',
    'tests/models/pubsub.js',
    'tests/models/system.js',
    'tests/models/errors.js',
    'tests/tracer/tracer_store.js',
    'tests/tracer/tracer.js',
    'tests/tracer/default_filters.js',
    'tests/check_for_oplog.js',
    'tests/error_tracking.js',
    'tests/wait_time_builder.js',
    'tests/hijack/set_labels.js',
    'tests/environment_variables.js',
  ], 'server');

  // common client
  api.add_files([
    'tests/client/utils.js',
    'tests/client/error_tracking.js',
    'tests/client/models/error.js',
    'tests/client/error_reporters/window_error.js',
    'tests/client/error_reporters/zone.js',
    'tests/client/error_reporters/meteor_debug.js',
  ], 'client');

  // common after
  api.add_files([
    'tests/common/default_error_filters.js',
    'tests/common/send.js'
  ], ['client', 'server']);
});

function configurePackage(api) {
  if(api.versionsFrom) {
    api.versionsFrom('METEOR@0.9.1');
    api.use('meteorhacks:meteorx@1.3.1');
    api.use('meteorhacks:zones@1.2.1', {weak: true});
  } else {
    // for Meteor releases <= 0.8.3
    // now, zones is a weak dependancy!
    // kadira on the client side knows how to handle it
    // api.use('zones');
    api.use('meteorx');
  }

  api.use([
    'minimongo', 'livedata', 'mongo-livedata', 'ejson',
    'underscore', 'http', 'email', 'random'
  ], ['server']);
  api.use(['underscore', 'random', 'jquery', 'localstorage'], ['client']);

  // common before
  api.add_files([
    'lib/common/unify.js',
    'lib/models/base_error.js'
  ], ['client', 'server']);

  // only server
  api.add_files([
    'lib/jobs.js',
    'lib/retry.js',
    'lib/utils.js',
    'lib/ntp.js',
    'lib/wait_time_builder.js',
    'lib/models/0model.js',
    'lib/models/methods.js',
    'lib/models/pubsub.js',
    'lib/models/system.js',
    'lib/models/errors.js',
    'lib/kadira.js',
    'lib/check_for_oplog.js',
    'lib/tracer/tracer.js',
    'lib/tracer/default_filters.js',
    'lib/tracer/tracer_store.js',
    'lib/hijack/wrap_server.js',
    'lib/hijack/wrap_session.js',
    'lib/hijack/wrap_subscription.js',
    'lib/hijack/wrap_observers.js',
    'lib/hijack/session.js',
    'lib/hijack/db.js',
    'lib/hijack/http.js',
    'lib/hijack/email.js',
    'lib/hijack/async.js',
    'lib/hijack/error.js',
    'lib/hijack/set_labels.js',
    'lib/environment_variables.js',
    'lib/auto_connect.js'
  ], 'server');

  // only client
  api.add_files([
    'lib/retry.js',
    'lib/ntp.js',
    'lib/client/utils.js',
    'lib/client/models/error.js',
    'lib/client/error_reporters/zone.js',
    'lib/client/error_reporters/window_error.js',
    'lib/client/error_reporters/meteor_debug.js',
    'lib/client/kadira.js'
  ], 'client');

  api.add_files([
    // It's possible to remove this file after some since this just contains
    // a notice to the user.
    // Actual implementation is in the meteorhacks:kadira-profiler package
    'lib/profiler/client.js',
  ], 'client');

  // common after
  api.add_files([
    'lib/common/default_error_filters.js',
    'lib/common/send.js'
  ], ['client', 'server']);
}
<|endoftext|>