<commit_before>var IMPLEMENTS = 'presence';
var INJECT = ['logger', 'config'];

var Presence = require('./presence');
var EventEmitter = require('events').EventEmitter;

function factory(services) {
  var logger = services.logger.getLogger('presence');

  var items = {};
  var parents = {};
  var children = {};

  var e = new EventEmitter();

  return {
    get: function (id) {
      var item = items[id];
      // if (!item) console.log(items, id, items[id]);
      return item;
    },
    getAll: function () {
      var arr = [];
      for (var i in items) {
        arr.push(items[i]);
      }
      return arr;
    },
    add: function(id, opts) {
      logger.debug('Adding ' + id);
      var p;
      var name = id;
      opts = opts || {};

      console.log('parent', opts.parent);

      if (opts.parent) {

        children[opts.parent] = children[opts.parent] || [];
        children[opts.parent].push(name);

        parents[name] = parents[name] || [];
        parents[name].push(opts.parent);

      }

      p = new Presence({
        id: name,
        logger: logger,
        timeout: opts.timeout,
        category: opts.category || null,
        name: opts.name || name
      });

      // if (opts.timeout > 0) {

      //   p = new Presence({
      //     id: name,
      //     logger: logger,
      //     timeout: opts.timeout,
      //   });

      // } else if (opts.timeout < 0) {

      //   p = new Presence({
      //     id: name,
      //     logger: logger,
      //     timeout: opts.timeout,
      //   });

      // } else {

      //   p = new Presence({
      //     id: name,
      //     logger: logger,
      //     timeout: opts.timeout,
      //   });

      // }

      items[id] = p;

      p.on('present', activate.bind(null, name));

      return p;
    },

    bump: function(id) {
      items[id].present();
    },

    isPresent: function(id) {
      return items[id].isPresent;
    },

    addParent: function(childId, parentId) {
      logger.debug('Adding '+parentId+' as parent of '+childId);

      children[childId] = children[childId] || [];
      children[childId].push(parentId);

      parents[parentId] = parents[parentId] || [];
      parents[parentId].push(childId);
    },

    removeParent: function(childId, parentId) {

    },

    on: e.on.bind(e),
    removeListener: e.removeListener.bind(e)
  };

  function activate(item, present) {
    var details = items[item];
    e.emit(item, present);
    e.emit('presence', {id:details.id, category:details.category, isPresent:details.isPresent, disabled:details.disabled});
    var ps = getParents(item);
    // console.log(ps);

    logger.debug('Parents of '+item, ps);

    ps.forEach(function (p) {
      if (present) p.childActivated();
      else p.childDeactivated();
    });
  }

  function getParents(child) {
    var p = parents[child];
    if (!p) return [];

    return p.map(function(id) {
      return items[id];
    })
    .filter(function (item) {
      return !!items;
    });
  }

  function getChildren(parent) {
    var c = children[child];
    if (!c) return [];

    return c.map(function(id) {
      return items[id];
    });
  }

}

module.exports = exports = factory;
exports.$implements = IMPLEMENTS;
exports.$inject = INJECT;<commit_msg>log length<commit_after>var IMPLEMENTS = 'presence';
var INJECT = ['logger', 'config'];

var Presence = require('./presence');
var EventEmitter = require('events').EventEmitter;

function factory(services) {
  var logger = services.logger.getLogger('presence');

  var items = {};
  var parents = {};
  var children = {};

  var e = new EventEmitter();

  return {
    get: function (id) {
      var item = items[id];
      // if (!item) console.log(items, id, items[id]);
      return item;
    },
    getAll: function () {
      var arr = [];
      for (var i in items) {
        arr.push(items[i]);
      }
      return arr;
    },
    add: function(id, opts) {
      logger.debug('Adding ' + id);
      var p;
      var name = id;
      opts = opts || {};

      console.log('parent', opts.parent);

      if (opts.parent) {

        children[opts.parent] = children[opts.parent] || [];
        children[opts.parent].push(name);

        parents[name] = parents[name] || [];
        parents[name].push(opts.parent);

      }

      p = new Presence({
        id: name,
        logger: logger,
        timeout: opts.timeout,
        category: opts.category || null,
        name: opts.name || name
      });

      // if (opts.timeout > 0) {

      //   p = new Presence({
      //     id: name,
      //     logger: logger,
      //     timeout: opts.timeout,
      //   });

      // } else if (opts.timeout < 0) {

      //   p = new Presence({
      //     id: name,
      //     logger: logger,
      //     timeout: opts.timeout,
      //   });

      // } else {

      //   p = new Presence({
      //     id: name,
      //     logger: logger,
      //     timeout: opts.timeout,
      //   });

      // }

      items[id] = p;

      p.on('present', activate.bind(null, name));

      return p;
    },

    bump: function(id) {
      items[id].present();
    },

    isPresent: function(id) {
      return items[id].isPresent;
    },

    addParent: function(childId, parentId) {
      logger.debug('Adding '+parentId+' as parent of '+childId);

      children[childId] = children[childId] || [];
      children[childId].push(parentId);

      parents[parentId] = parents[parentId] || [];
      parents[parentId].push(childId);
    },

    removeParent: function(childId, parentId) {

    },

    on: e.on.bind(e),
    removeListener: e.removeListener.bind(e)
  };

  function activate(item, present) {
    var details = items[item];
    e.emit(item, present);
    e.emit('presence', {id:details.id, category:details.category, isPresent:details.isPresent, disabled:details.disabled});
    var ps = getParents(item);
    // console.log(ps);

    logger.debug('Parents of '+item+' are '+ps.length);

    ps.forEach(function (p) {
      if (present) p.childActivated();
      else p.childDeactivated();
    });
  }

  function getParents(child) {
    var p = parents[child];
    if (!p) return [];

    return p.map(function(id) {
      return items[id];
    })
    .filter(function (item) {
      return !!items;
    });
  }

  function getChildren(parent) {
    var c = children[child];
    if (!c) return [];

    return c.map(function(id) {
      return items[id];
    });
  }

}

module.exports = exports = factory;
exports.$implements = IMPLEMENTS;
exports.$inject = INJECT;<|endoftext|>


<commit_before>'use strict';

module.exports = function (nitro) {

  var rollup = nitro.require('rollup')

  function _copyObject(src) {
    var result = {};
    for( var key in src ) result[key] = _copy(src[key]);
    return result;
  }

  function _copy (src) {
    if( src instanceof Array ) return src.slice();
    if( typeof src === 'object' && src !== null ) return _copyObject(src);
    return src;
  }

  return function (list, options) {

    var bundleSync = nitro.deasync(function (f, callback) {
      var options = Object.assign({
        commonjs: {
          include: 'node_modules/**',
        },
        resolve: {
          module: true, // Default: true
          browser: true,  // Default: false
        },
        babel: {
          exclude: 'node_modules/**',
        },
      }, options || {})

      var _options = options ? _copy(options) : {}

      var _output = _options.output ? _copy(_options.output) : {}
      _output.filename = _output.filename || f.filename

      if( _output.path && !/^\//.test(_output.path) ) _output.path = nitro.joinPaths.root(_output.path)

      _options.output = _output
      _options.input = f.full_path

      var _plugins = []
      if( options.commonjs ) _plugins.push( nitro.require('rollup-plugin-commonjs')(options.commonjs) )
      if( options.resolve ) _plugins.push( nitro.require('rollup-plugin-node-resolve')(options.resolve) )
      if( options.babel ) _plugins.push( nitro.require('rollup-plugin-babel')(options.babel) )
      if( options.virtual ) _plugins.push( nitro.require('rollup-plugin-virtual')(options.virtual) )

      if( options.plugins ) _plugins.push.apply(_plugins, options.plugins)

      rollup.rollup( Object.assign({
        input: path.join(process.cwd(), filepath),
        context: 'window',
        plugins: _plugins,
      }, options.input || {}) ).then(function (bundle) {
        bundle.generate( Object.assign({
          format: 'iife',
          name: options.output_name,
          // name: 'aplazame',
          strict: false,
        }, options.output || {}) ).then(function (result) {
          callback(null, result.output[0].code)
        }, function (reason) {
          callback(reason)
        })

      }, function (reason) {
        callback(reason);
      })

    })

    return list.each(function (f) {
      f.src = bundleSync(f)
    })
  }

}
<commit_msg>rollup fixes<commit_after>'use strict';

module.exports = function (nitro) {

  var rollup = nitro.require('rollup')

  return function (list, options) {

    var bundleSync = nitro.deasync(function (f, callback) {
      options = Object.assign({
        commonjs: {
          include: 'node_modules/**',
        },
        resolve: {},
        babel: {
          exclude: 'node_modules/**',
        },
      }, options || {})

      if( options.path && !/^\//.test(options.path) ) options.path = nitro.joinPaths.root(options.path)

      var _plugins = []
      if( options.commonjs ) _plugins.push( nitro.require('rollup-plugin-commonjs')(options.commonjs) )
      if( options.resolve ) _plugins.push( nitro.require('rollup-plugin-node-resolve')(options.resolve) )
      if( options.babel ) _plugins.push( nitro.require('rollup-plugin-babel')(options.babel) )
      if( options.virtual ) _plugins.push( nitro.require('rollup-plugin-virtual')(options.virtual) )

      if( options.plugins ) _plugins.push.apply(_plugins, options.plugins)

      rollup.rollup( Object.assign({
        input: f.full_path,
        context: 'window',
        plugins: _plugins,
      }, options.input || {}) ).then(function (bundle) {
        bundle.generate( Object.assign({
          format: 'iife',
          name: options.output_name,
          // name: 'aplazame',
          strict: false,
        }, options.output || {}) ).then(function (result) {
          callback(null, result.output[0].code)
        }, function (reason) {
          callback(reason)
        })

      }, function (reason) {
        callback(reason);
      })

    })

    return list.each(function (f) {
      f.src = bundleSync(f)
    })
  }

}
<|endoftext|>


<commit_before>'use strict';

// Query Compiler
// -------

var _       = require('lodash');
var helpers = require('../helpers');
var Raw     = require('../raw');

// The "QueryCompiler" takes all of the query statements which have been
// gathered in the "QueryBuilder" and turns them into a properly formatted / bound
// query string.
function QueryCompiler(queryBuilder) {
  this.method      = queryBuilder._method || 'select';
  this.options     = queryBuilder._options;
  this.single      = queryBuilder._single;
  this.transacting = queryBuilder._transacting;
  this.grouped     = _.groupBy(queryBuilder._statements, 'grouping');
  this.tableName   = this.single.table ? this.formatter.wrap(this.single.table) : '';
}

// Collapse the builder into a single object
QueryCompiler.prototype.toSQL = function(method) {
  var val = this[method]();
  var defaults = {
    method: method,
    options: this.options && this.options.length > 0 ?
      _.extend.apply(_, this.options) : void 0,
    bindings: this.formatter.bindings
  };
  if (_.isString(val)) {
    val = {sql: val};
  }
  if (method === 'select' && this.single.as) {
    defaults.as = this.single.as;
  }
  return _.extend(defaults, val);
};

var components = [
  'columns', 'join', 'where', 'union', 'group',
  'having', 'order', 'limit', 'offset', 'lock'
];

// Compiles the `select` statement, or nested sub-selects
// by calling each of the component compilers, trimming out
// the empties, and returning a generated query string.
QueryCompiler.prototype.select = function() {
  var statements = [];
  for (var i = 0, l = components.length; i < l; i++) {
    var component = components[i];
    statements.push(this[component](this));
  }
  return _.compact(statements).join(' ');
};
QueryCompiler.prototype.first = QueryCompiler.prototype.select;
QueryCompiler.prototype.pluck = function() {
  return {
    sql: this.select(),
    pluck: this.single.pluck
  };
};

// Compiles an "insert" query, allowing for multiple
// inserts using a single query statement.
QueryCompiler.prototype.insert = function() {
  var self = this;
  var insertValues = this.single.insert;

  var sql = 'insert into ' + this.tableName + ' ';

  if (_.isArray(insertValues) && (insertValues.length === 1) && _.isEmpty(insertValues[0])) {
    insertValues = [];
  }

  if (_.isEmpty(insertValues) && !_.isFunction(insertValues)) {
    sql += this._emptyInsertValue;
  } else {
    var insertData = this._prepInsert(insertValues);

    if (_.isString(insertData)) {
      sql += insertData;
    } else  {
      if (insertData.columns.length) {
        sql += '(' + this.formatter.columnize(insertData.columns) + ') values (' +
          _.map(insertData.values, this.formatter.parameterize, this.formatter).join('), (') + ')';
      } else {
        // if there is no target column only insert default values
        sql += '() values ' + _.map(insertData.values, function () { return '(' + (self._defaultInsertValue || '') + ')'; }).join(', ');
      }
    }
  }
  return sql;
};

// Compiles the "update" query.
QueryCompiler.prototype.update = function() {
  var updateData = this._prepUpdate(this.single.update);
  var wheres     = this.where();
  return 'update ' + this.tableName +
    ' set ' + updateData.join(', ') +
    (wheres ? ' ' + wheres : '');
};

// Compiles the columns in the query, specifying if an item was distinct.
QueryCompiler.prototype.columns = function() {
  var distinct = false;
  if (this.onlyUnions()) return '';
  var columns = this.grouped.columns || [];
  var sql = [];
  if (columns) {
    for (var i = 0, l = columns.length; i < l; i++) {
      var stmt = columns[i];
      if (stmt.distinct) distinct = true;
      if (stmt.type === 'aggregate') {
        sql.push(this.aggregate(stmt));
      } else if (stmt.value && stmt.value.length > 0) {
        sql.push(this.formatter.columnize(stmt.value));
      }
    }
  }
  if (sql.length === 0) sql.push('*');
  return 'select ' + (distinct ? 'distinct ' : '') +
      (sql.join(', ') || '*') + (this.tableName ? ' from ' + this.tableName : '');
};

QueryCompiler.prototype.aggregate = function(stmt) {
  var val = stmt.value;
  var splitOn = val.toLowerCase().indexOf(' as ');
  // Allows us to speciy an alias for the aggregate types.
  if (splitOn !== -1) {
    var col = val.slice(0, splitOn);
    var alias = val.slice(splitOn + 4);
    return stmt.method + '(' + this.formatter.wrap(col) + ') as ' + this.formatter.wrap(alias);
  }
  return stmt.method + '(' + this.formatter.wrap(val) + ')';
};

// Compiles all each of the `join` clauses on the query,
// including any nested join queries.
QueryCompiler.prototype.join = function() {
  var joins = this.grouped.join;
  if (!joins) return '';
  var sql = _.reduce(joins, function(acc, join) {
    if (join.joinType === 'raw') {
      acc.push(this.formatter.checkRaw(join.table));
    } else {
      acc.push(join.joinType + ' join ' + this.formatter.wrap(join.table));
      _.each(join.clauses, function(clause, i) {
        acc.push(i > 0 ? clause[1] : clause[0]);
        acc.push(this.formatter.wrap(clause[2]));
        if (clause[3]) acc.push(this.formatter.operator(clause[3]));
        if (clause[4]) acc.push(this.formatter.wrap(clause[4]));
      }, this);
    }
    return acc;
  }, [], this);
  return sql.length > 0 ? sql.join(' ') : '';
};

// Compiles all `where` statements on the query.
QueryCompiler.prototype.where = function() {
  var wheres = this.grouped.where;
  if (!wheres) return;
  var sql = [];
  sql[0] = 'where';
  for (var i = 0, l = wheres.length; i < l; i++) {
    var stmt = wheres[i];
    if (i !== 0) sql.push(stmt.bool);
    sql.push(this[stmt.type](stmt));
  }
  return sql.length > 1 ? sql.join(' ') : '';
};

QueryCompiler.prototype.group = function() {
  return this._groupsOrders('group');
};
QueryCompiler.prototype.order = function() {
  return this._groupsOrders('order');
};

// Compiles the `having` statements.
QueryCompiler.prototype.having = function() {
  var havings = this.grouped.having;
  if (!havings) return '';
  var sql = ['having'];
  for (var i = 0, l = havings.length; i < l; i++) {
    var str = '', s = havings[i];
    if (i !== 0) str = s.bool + ' ';
    if (s.type === 'havingBasic') {
      sql.push(str + this.formatter.columnize(s.column) + ' ' +
        this.formatter.operator(s.operator) + ' ' + this.formatter.parameter(s.value));
    }else{
      if(s.type === 'whereWrapped'){
        sql.push(this.whereWrapped(s));
      } else {
        sql.push(str + this.formatter.checkRaw(s.value));
      }
    }
  }
  return sql.length > 1 ? sql.join(' ') : '';
};

// Compile the "union" queries attached to the main query.
QueryCompiler.prototype.union = function() {
  var onlyUnions = this.onlyUnions();
  var unions = this.grouped.union;
  if (!unions) return '';
  var sql = '';
  for (var i = 0, l = unions.length; i < l; i++) {
    var union = unions[i];
    if (i > 0) sql += ' ';
    if (i > 0 || !onlyUnions) sql += union.clause + ' ';
    var statement = this.formatter.rawOrFn(union.value);
    if (statement) {
      if (union.wrap) sql += '(';
      sql += statement;
      if (union.wrap) sql += ')';
    }
  }
  return sql;
};

// If we haven't specified any columns or a `tableName`, we're assuming this
// is only being used for unions.
QueryCompiler.prototype.onlyUnions = function() {
  return (!this.grouped.columns && this.grouped.union && !this.tableName);
};

QueryCompiler.prototype.limit = function() {
  var noLimit = !this.single.limit && this.single.limit !== 0;
  if (noLimit) return '';
  return 'limit ' + this.formatter.parameter(this.single.limit);
};

QueryCompiler.prototype.offset = function() {
  if (!this.single.offset) return '';
  return 'offset ' + this.formatter.parameter(this.single.offset);
};

// Compiles a `delete` query.
QueryCompiler.prototype.del = function() {
  var wheres = this.where();
  return 'delete from ' + this.tableName +
    (wheres ? ' ' + wheres : '');
};

// Compiles a `truncate` query.
QueryCompiler.prototype.truncate = function() {
  return 'truncate ' + this.tableName;
};

// Compiles the "locks".
QueryCompiler.prototype.lock = function() {
  if (this.single.lock) {
    if (!this.transacting) {
      helpers.warn('You are attempting to perform a "lock" command outside of a transaction.');
    } else {
      return this[this.single.lock]();
    }
  }
};

// Compile the "counter".
QueryCompiler.prototype.counter = function() {
  var counter = this.single.counter;
  var toUpdate = {};
  toUpdate[counter.column] = new Raw(this.formatter.wrap(counter.column) +
    ' ' + (counter.symbol || '+') +
    ' ' + counter.amount);
  this.single.update = toUpdate;
  return this.update();
};

// Compiles the `order by` statements.
QueryCompiler.prototype._groupsOrders = function(type) {
  var items = this.grouped[type];
  if (!items) return '';
  var formatter = this.formatter;
  var sql = items.map(function (item) {
    return (item.value instanceof Raw ? formatter.checkRaw(item.value) : formatter.columnize(item.value)) +
      ((type === 'order' && item.type !== 'orderByRaw') ? ' ' + formatter.direction(item.direction) : '');
  });
  return sql.length ? type + ' by ' + sql.join(', ') : '';
};

// Where Clause
// ------

QueryCompiler.prototype.whereIn = function(statement) {
  if (_.isArray(statement.column)) return this.multiWhereIn(statement);
  return this.formatter.wrap(statement.column) + ' ' + this._not(statement, 'in ') +
    this.wrap(this.formatter.parameterize(statement.value));
};

QueryCompiler.prototype.multiWhereIn = function(statement) {
  return '(' + _.map(statement.column, this.formatter.wrap, this.formatter) + ') ' +
    this._not(statement, 'in ') + '((' +
    _.map(statement.value, this.formatter.parameterize, this.formatter).join('),(') + '))';
};

QueryCompiler.prototype.whereNull = function(statement) {
  return this.formatter.wrap(statement.column) + ' is ' + this._not(statement, 'null');
};

// Compiles a basic "where" clause.
QueryCompiler.prototype.whereBasic = function(statement) {
  return this.formatter.wrap(statement.column) + ' ' +
    this.formatter.operator(statement.operator) + ' ' +
    this.formatter.parameter(statement.value);
};

QueryCompiler.prototype.whereExists = function(statement) {
  return this._not(statement, 'exists') + ' (' + this.formatter.rawOrFn(statement.value) + ')';
};

QueryCompiler.prototype.whereWrapped = function(statement) {
  return '(' + this.formatter.rawOrFn(statement.value, 'where').slice(6) + ')';
};

QueryCompiler.prototype.whereBetween = function(statement) {
  return this.formatter.wrap(statement.column) + ' ' + this._not(statement, 'between') + ' ' +
    _.map(statement.value, this.formatter.parameter, this.formatter).join(' and ');
};

// Compiles a "whereRaw" query.
QueryCompiler.prototype.whereRaw = function(statement) {
  return this.formatter.checkRaw(statement.value);
};

QueryCompiler.prototype.wrap = function(str) {
  if (str.charAt(0) !== '(') return '(' + str + ')';
  return str;
};

// Determines whether to add a "not" prefix to the where clause.
QueryCompiler.prototype._not = function(statement, str) {
  if (statement.not) return 'not ' + str;
  return str;
};

// "Preps" the insert.
QueryCompiler.prototype._prepInsert = function(data) {
  var isRaw = this.formatter.rawOrFn(data);
  if (isRaw) return isRaw;
  var values = [];
  var columns, colList;
  if (!_.isArray(data)) data = data ? [data] : [];
  for (var i = 0, l = data.length; i<l; i++) {
    var sorted = helpers.sortObject(data[i]);
    columns = _.pluck(sorted, 0);
    colList = colList || columns;
    if (!_.isEqual(columns, colList)) {
      return this._prepInsert(this._normalizeInsert(data));
    }
    values.push(_.pluck(sorted, 1));
  }
  return {
    columns: columns,
    values: values
  };
};

// If we are running an insert with variable object keys, we need to normalize
// for the missing keys, presumably setting the values to undefined.
QueryCompiler.prototype._normalizeInsert = function(data) {
  if (!_.isArray(data)) return _.clone(data);
  var defaultObj = _.reduce(_.union.apply(_, _.map(data, function(val) {
    return _.keys(val);
  })), function(memo, key) {
    memo[key] = void 0;
    return memo;
  }, {});
  return _.map(data, function(row) { return _.defaults(row, defaultObj); });
};

// "Preps" the update.
QueryCompiler.prototype._prepUpdate = function(data) {
  var vals = [];
  var sorted = helpers.sortObject(data);
  for (var i = 0, l = sorted.length; i < l; i++) {
    vals.push(this.formatter.wrap(sorted[i][0]) + ' = ' + this.formatter.parameter(sorted[i][1]));
  }
  return vals;
};

module.exports = QueryCompiler;
<commit_msg>Don't pass tableName through the formatter until it's needed.<commit_after>'use strict';

// Query Compiler
// -------

var _       = require('lodash');
var helpers = require('../helpers');
var Raw     = require('../raw');

// The "QueryCompiler" takes all of the query statements which have been
// gathered in the "QueryBuilder" and turns them into a properly formatted / bound
// query string.
function QueryCompiler(queryBuilder) {
  this.method      = queryBuilder._method || 'select';
  this.options     = queryBuilder._options;
  this.single      = queryBuilder._single;
  this.transacting = queryBuilder._transacting;
  this.grouped     = _.groupBy(queryBuilder._statements, 'grouping');
}

// Collapse the builder into a single object
QueryCompiler.prototype.toSQL = function(method) {
  var val = this[method]();
  var defaults = {
    method: method,
    options: this.options && this.options.length > 0 ?
      _.extend.apply(_, this.options) : void 0,
    bindings: this.formatter.bindings
  };
  if (_.isString(val)) {
    val = {sql: val};
  }
  if (method === 'select' && this.single.as) {
    defaults.as = this.single.as;
  }
  return _.extend(defaults, val);
};

// Get the table name, wrapping it if necessary.
// Implemented as a property to prevent ordering issues as described in #704.
Object.defineProperty(QueryCompiler.prototype, 'tableName', {
  get: function() {
    if(!this._tableName) {
      // Only call this.formatter.wrap() the first time this property is accessed.
      this._tableName = this.single.table ? this.formatter.wrap(this.single.table) : '';
    }
    return this._tableName;
  }
});

var components = [
  'columns', 'join', 'where', 'union', 'group',
  'having', 'order', 'limit', 'offset', 'lock'
];

// Compiles the `select` statement, or nested sub-selects
// by calling each of the component compilers, trimming out
// the empties, and returning a generated query string.
QueryCompiler.prototype.select = function() {
  var statements = [];
  for (var i = 0, l = components.length; i < l; i++) {
    var component = components[i];
    statements.push(this[component](this));
  }
  return _.compact(statements).join(' ');
};
QueryCompiler.prototype.first = QueryCompiler.prototype.select;
QueryCompiler.prototype.pluck = function() {
  return {
    sql: this.select(),
    pluck: this.single.pluck
  };
};

// Compiles an "insert" query, allowing for multiple
// inserts using a single query statement.
QueryCompiler.prototype.insert = function() {
  var self = this;
  var insertValues = this.single.insert;

  var sql = 'insert into ' + this.tableName + ' ';

  if (_.isArray(insertValues) && (insertValues.length === 1) && _.isEmpty(insertValues[0])) {
    insertValues = [];
  }

  if (_.isEmpty(insertValues) && !_.isFunction(insertValues)) {
    sql += this._emptyInsertValue;
  } else {
    var insertData = this._prepInsert(insertValues);

    if (_.isString(insertData)) {
      sql += insertData;
    } else  {
      if (insertData.columns.length) {
        sql += '(' + this.formatter.columnize(insertData.columns) + ') values (' +
          _.map(insertData.values, this.formatter.parameterize, this.formatter).join('), (') + ')';
      } else {
        // if there is no target column only insert default values
        sql += '() values ' + _.map(insertData.values, function () { return '(' + (self._defaultInsertValue || '') + ')'; }).join(', ');
      }
    }
  }
  return sql;
};

// Compiles the "update" query.
QueryCompiler.prototype.update = function() {
  // Make sure tableName is processed by the formatter first.
  var tableName  = this.tableName;
  var updateData = this._prepUpdate(this.single.update);
  var wheres     = this.where();
  return 'update ' + tableName +
    ' set ' + updateData.join(', ') +
    (wheres ? ' ' + wheres : '');
};

// Compiles the columns in the query, specifying if an item was distinct.
QueryCompiler.prototype.columns = function() {
  var distinct = false;
  if (this.onlyUnions()) return '';
  var columns = this.grouped.columns || [];
  var sql = [];
  if (columns) {
    for (var i = 0, l = columns.length; i < l; i++) {
      var stmt = columns[i];
      if (stmt.distinct) distinct = true;
      if (stmt.type === 'aggregate') {
        sql.push(this.aggregate(stmt));
      } else if (stmt.value && stmt.value.length > 0) {
        sql.push(this.formatter.columnize(stmt.value));
      }
    }
  }
  if (sql.length === 0) sql.push('*');
  return 'select ' + (distinct ? 'distinct ' : '') +
      (sql.join(', ') || '*') + (this.tableName ? ' from ' + this.tableName : '');
};

QueryCompiler.prototype.aggregate = function(stmt) {
  var val = stmt.value;
  var splitOn = val.toLowerCase().indexOf(' as ');
  // Allows us to speciy an alias for the aggregate types.
  if (splitOn !== -1) {
    var col = val.slice(0, splitOn);
    var alias = val.slice(splitOn + 4);
    return stmt.method + '(' + this.formatter.wrap(col) + ') as ' + this.formatter.wrap(alias);
  }
  return stmt.method + '(' + this.formatter.wrap(val) + ')';
};

// Compiles all each of the `join` clauses on the query,
// including any nested join queries.
QueryCompiler.prototype.join = function() {
  var joins = this.grouped.join;
  if (!joins) return '';
  var sql = _.reduce(joins, function(acc, join) {
    if (join.joinType === 'raw') {
      acc.push(this.formatter.checkRaw(join.table));
    } else {
      acc.push(join.joinType + ' join ' + this.formatter.wrap(join.table));
      _.each(join.clauses, function(clause, i) {
        acc.push(i > 0 ? clause[1] : clause[0]);
        acc.push(this.formatter.wrap(clause[2]));
        if (clause[3]) acc.push(this.formatter.operator(clause[3]));
        if (clause[4]) acc.push(this.formatter.wrap(clause[4]));
      }, this);
    }
    return acc;
  }, [], this);
  return sql.length > 0 ? sql.join(' ') : '';
};

// Compiles all `where` statements on the query.
QueryCompiler.prototype.where = function() {
  var wheres = this.grouped.where;
  if (!wheres) return;
  var sql = [];
  sql[0] = 'where';
  for (var i = 0, l = wheres.length; i < l; i++) {
    var stmt = wheres[i];
    if (i !== 0) sql.push(stmt.bool);
    sql.push(this[stmt.type](stmt));
  }
  return sql.length > 1 ? sql.join(' ') : '';
};

QueryCompiler.prototype.group = function() {
  return this._groupsOrders('group');
};
QueryCompiler.prototype.order = function() {
  return this._groupsOrders('order');
};

// Compiles the `having` statements.
QueryCompiler.prototype.having = function() {
  var havings = this.grouped.having;
  if (!havings) return '';
  var sql = ['having'];
  for (var i = 0, l = havings.length; i < l; i++) {
    var str = '', s = havings[i];
    if (i !== 0) str = s.bool + ' ';
    if (s.type === 'havingBasic') {
      sql.push(str + this.formatter.columnize(s.column) + ' ' +
        this.formatter.operator(s.operator) + ' ' + this.formatter.parameter(s.value));
    }else{
      if(s.type === 'whereWrapped'){
        sql.push(this.whereWrapped(s));
      } else {
        sql.push(str + this.formatter.checkRaw(s.value));
      }
    }
  }
  return sql.length > 1 ? sql.join(' ') : '';
};

// Compile the "union" queries attached to the main query.
QueryCompiler.prototype.union = function() {
  var onlyUnions = this.onlyUnions();
  var unions = this.grouped.union;
  if (!unions) return '';
  var sql = '';
  for (var i = 0, l = unions.length; i < l; i++) {
    var union = unions[i];
    if (i > 0) sql += ' ';
    if (i > 0 || !onlyUnions) sql += union.clause + ' ';
    var statement = this.formatter.rawOrFn(union.value);
    if (statement) {
      if (union.wrap) sql += '(';
      sql += statement;
      if (union.wrap) sql += ')';
    }
  }
  return sql;
};

// If we haven't specified any columns or a `tableName`, we're assuming this
// is only being used for unions.
QueryCompiler.prototype.onlyUnions = function() {
  return (!this.grouped.columns && this.grouped.union && !this.tableName);
};

QueryCompiler.prototype.limit = function() {
  var noLimit = !this.single.limit && this.single.limit !== 0;
  if (noLimit) return '';
  return 'limit ' + this.formatter.parameter(this.single.limit);
};

QueryCompiler.prototype.offset = function() {
  if (!this.single.offset) return '';
  return 'offset ' + this.formatter.parameter(this.single.offset);
};

// Compiles a `delete` query.
QueryCompiler.prototype.del = function() {
  // Make sure tableName is processed by the formatter first.
  var tableName  = this.tableName;
  var wheres = this.where();
  return 'delete from ' + tableName +
    (wheres ? ' ' + wheres : '');
};

// Compiles a `truncate` query.
QueryCompiler.prototype.truncate = function() {
  return 'truncate ' + this.tableName;
};

// Compiles the "locks".
QueryCompiler.prototype.lock = function() {
  if (this.single.lock) {
    if (!this.transacting) {
      helpers.warn('You are attempting to perform a "lock" command outside of a transaction.');
    } else {
      return this[this.single.lock]();
    }
  }
};

// Compile the "counter".
QueryCompiler.prototype.counter = function() {
  var counter = this.single.counter;
  var toUpdate = {};
  toUpdate[counter.column] = new Raw(this.formatter.wrap(counter.column) +
    ' ' + (counter.symbol || '+') +
    ' ' + counter.amount);
  this.single.update = toUpdate;
  return this.update();
};

// Compiles the `order by` statements.
QueryCompiler.prototype._groupsOrders = function(type) {
  var items = this.grouped[type];
  if (!items) return '';
  var formatter = this.formatter;
  var sql = items.map(function (item) {
    return (item.value instanceof Raw ? formatter.checkRaw(item.value) : formatter.columnize(item.value)) +
      ((type === 'order' && item.type !== 'orderByRaw') ? ' ' + formatter.direction(item.direction) : '');
  });
  return sql.length ? type + ' by ' + sql.join(', ') : '';
};

// Where Clause
// ------

QueryCompiler.prototype.whereIn = function(statement) {
  if (_.isArray(statement.column)) return this.multiWhereIn(statement);
  return this.formatter.wrap(statement.column) + ' ' + this._not(statement, 'in ') +
    this.wrap(this.formatter.parameterize(statement.value));
};

QueryCompiler.prototype.multiWhereIn = function(statement) {
  return '(' + _.map(statement.column, this.formatter.wrap, this.formatter) + ') ' +
    this._not(statement, 'in ') + '((' +
    _.map(statement.value, this.formatter.parameterize, this.formatter).join('),(') + '))';
};

QueryCompiler.prototype.whereNull = function(statement) {
  return this.formatter.wrap(statement.column) + ' is ' + this._not(statement, 'null');
};

// Compiles a basic "where" clause.
QueryCompiler.prototype.whereBasic = function(statement) {
  return this.formatter.wrap(statement.column) + ' ' +
    this.formatter.operator(statement.operator) + ' ' +
    this.formatter.parameter(statement.value);
};

QueryCompiler.prototype.whereExists = function(statement) {
  return this._not(statement, 'exists') + ' (' + this.formatter.rawOrFn(statement.value) + ')';
};

QueryCompiler.prototype.whereWrapped = function(statement) {
  return '(' + this.formatter.rawOrFn(statement.value, 'where').slice(6) + ')';
};

QueryCompiler.prototype.whereBetween = function(statement) {
  return this.formatter.wrap(statement.column) + ' ' + this._not(statement, 'between') + ' ' +
    _.map(statement.value, this.formatter.parameter, this.formatter).join(' and ');
};

// Compiles a "whereRaw" query.
QueryCompiler.prototype.whereRaw = function(statement) {
  return this.formatter.checkRaw(statement.value);
};

QueryCompiler.prototype.wrap = function(str) {
  if (str.charAt(0) !== '(') return '(' + str + ')';
  return str;
};

// Determines whether to add a "not" prefix to the where clause.
QueryCompiler.prototype._not = function(statement, str) {
  if (statement.not) return 'not ' + str;
  return str;
};

// "Preps" the insert.
QueryCompiler.prototype._prepInsert = function(data) {
  var isRaw = this.formatter.rawOrFn(data);
  if (isRaw) return isRaw;
  var values = [];
  var columns, colList;
  if (!_.isArray(data)) data = data ? [data] : [];
  for (var i = 0, l = data.length; i<l; i++) {
    var sorted = helpers.sortObject(data[i]);
    columns = _.pluck(sorted, 0);
    colList = colList || columns;
    if (!_.isEqual(columns, colList)) {
      return this._prepInsert(this._normalizeInsert(data));
    }
    values.push(_.pluck(sorted, 1));
  }
  return {
    columns: columns,
    values: values
  };
};

// If we are running an insert with variable object keys, we need to normalize
// for the missing keys, presumably setting the values to undefined.
QueryCompiler.prototype._normalizeInsert = function(data) {
  if (!_.isArray(data)) return _.clone(data);
  var defaultObj = _.reduce(_.union.apply(_, _.map(data, function(val) {
    return _.keys(val);
  })), function(memo, key) {
    memo[key] = void 0;
    return memo;
  }, {});
  return _.map(data, function(row) { return _.defaults(row, defaultObj); });
};

// "Preps" the update.
QueryCompiler.prototype._prepUpdate = function(data) {
  var vals = [];
  var sorted = helpers.sortObject(data);
  for (var i = 0, l = sorted.length; i < l; i++) {
    vals.push(this.formatter.wrap(sorted[i][0]) + ' = ' + this.formatter.parameter(sorted[i][1]));
  }
  return vals;
};

module.exports = QueryCompiler;
<|endoftext|>


<commit_before>var redisAdapter = require('redis'),
    Promise = require('bluebird'),
    updateInfo = require('./updateInfo');

exports.connect = function(settings){
    Promise.promisifyAll(redisAdapter);
    redis = redisAdapter.createClient(settings.port, settings.host, settings.options);
    if(settings.password){
        redis.auth(settings.password);
    }
    redis.on("error", console.log);
    updateInfo.startUpdatingInfo();
};
<commit_msg>Support Redis URL<commit_after>var redisAdapter = require('redis'),
    Promise = require('bluebird'),
    updateInfo = require('./updateInfo');

exports.connect = function(settings){
    var redis;

    Promise.promisifyAll(redisAdapter);
    if(settings.url) {
        redis = redisAdapter.createClient(settings.url, settings.options);
    } else {
        redis = redisAdapter.createClient(settings.port, settings.host, settings.options);
        if(settings.password){
            redis.auth(settings.password);
        }
    }
    redis.on("error", console.log);
    updateInfo.startUpdatingInfo();
};
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var Class = require('../util/class');
var RelationTrigger = require('./trigger');
var property = require('../util/property').fn;
var inflection = require('../util/inflection');

_.str = require('underscore.string');

/**
 * Documentation forthcoming.
 *
 * @since 1.0
 * @public
 * @constructor BaseRelation
 * @extends Class
 */
var BaseRelation = Class.extend(/** @lends BaseRelation# */ {
  init: function(/*name, modelClass, relatedModel, options*/) {
    var args = Array.prototype.slice.call(arguments);
    var name = args.shift();
    var modelClass = args.shift();
    var db = modelClass.db;
    var relatedModel;

    if (args[0] instanceof db.Model.__metaclass__) {
      relatedModel = args.shift();
    }
    else if (_.isString(args[0])) {
      relatedModel = db.model(args.shift());
    }
    else {
      relatedModel = db.model(inflection.singularize(name));
    }

    var options = args.shift();

    this._name = name;
    this._modelClass = modelClass;
    this._relatedModel = relatedModel;
    this._options = options || {};
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @private
   * @method
   */
  template: function(key) {
    var name = this._name;
    var singular = inflection.singularize(name);
    var plural = inflection.pluralize(singular);
    var singularCapitalized = _.str.capitalize(singular);
    var pluralCapitalized = _.str.capitalize(plural);
    return key
      .replace('<singular>', singular)
      .replace('<Singular>', singularCapitalized)
      .replace('<plural>', plural)
      .replace('<Plural>', pluralCapitalized);
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @protected
   * @method
   */
  methods: function() {
    var self = this;
    var name = this._name;
    var methods = this.__identity__.methods;
    var names = _.reduce(methods, function(result, method, key) {
      result[key] = self.template(key); return result;
    }, {});
    return _.reduce(methods, function(result, method, key) {
      result[self.template(key)] = method(self, {
        name: name,
        names: names
      });
      return result;
    }, {});
  }
});

BaseRelation.reopenClass(/** @lends BaseRelation */ {

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @protected
   * @method
   */
  property: function(getterName, setterName) {
    return function(relation) {
      var getter = getterName && function() {
        return relation[getterName](this);
      };
      var setter = setterName && function(value) {
        return relation[setterName](this, value);
      };
      return property(getter, setter);
    };
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @protected
   * @method
   */
  method: function(name) {
    return function(relation) {
      return function() {
        return relation[name](this, arguments);
      };
    };
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @public
   * @method
   */
  attribute: function() {
    return _.partial(RelationTrigger.create.bind(RelationTrigger), this);
  }

});

module.exports = BaseRelation.reopenClass({ __name__: 'BaseRelation' });
<commit_msg>Added base class implementations for methods that must be overridden.<commit_after>'use strict';

var _ = require('lodash');
var Class = require('../util/class');
var RelationTrigger = require('./trigger');
var property = require('../util/property').fn;
var inflection = require('../util/inflection');

_.str = require('underscore.string');

/**
 * Documentation forthcoming.
 *
 * @since 1.0
 * @public
 * @constructor BaseRelation
 * @extends Class
 */
var BaseRelation = Class.extend(/** @lends BaseRelation# */ {
  init: function(/*name, modelClass, relatedModel, options*/) {
    var args = Array.prototype.slice.call(arguments);
    var name = args.shift();
    var modelClass = args.shift();
    var db = modelClass.db;
    var relatedModel;

    if (args[0] instanceof db.Model.__metaclass__) {
      relatedModel = args.shift();
    }
    else if (_.isString(args[0])) {
      relatedModel = db.model(args.shift());
    }
    else {
      relatedModel = db.model(inflection.singularize(name));
    }

    var options = args.shift();

    this._name = name;
    this._modelClass = modelClass;
    this._relatedModel = relatedModel;
    this._options = options || {};
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @private
   * @method
   */
  template: function(key) {
    var name = this._name;
    var singular = inflection.singularize(name);
    var plural = inflection.pluralize(singular);
    var singularCapitalized = _.str.capitalize(singular);
    var pluralCapitalized = _.str.capitalize(plural);
    return key
      .replace('<singular>', singular)
      .replace('<Singular>', singularCapitalized)
      .replace('<plural>', plural)
      .replace('<Plural>', pluralCapitalized);
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @protected
   * @method
   */
  methods: function() {
    var self = this;
    var name = this._name;
    var methods = this.__identity__.methods;
    var names = _.reduce(methods, function(result, method, key) {
      result[key] = self.template(key); return result;
    }, {});
    return _.reduce(methods, function(result, method, key) {
      result[self.template(key)] = method(self, {
        name: name,
        names: names
      });
      return result;
    }, {});
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @protected
   * @method
   */
  associate: function(/*instance, relatedObject, options*/) {
    throw new Error('The `associate` method must be implemented by subclass');
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @protected
   * @method
   */
  disassociate: function(/*instance, relatedObject, options*/) {
    throw new Error('The `disassociate` method must be implemented by subclass');
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @protected
   * @method
   */
  prefetch: function(/*instances*/) {
    throw new Error('The `prefetch` method must be implemented by subclass');
  }
});

BaseRelation.reopenClass(/** @lends BaseRelation */ {

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @protected
   * @method
   */
  property: function(getterName, setterName) {
    return function(relation) {
      var getter = getterName && function() {
        return relation[getterName](this);
      };
      var setter = setterName && function(value) {
        return relation[setterName](this, value);
      };
      return property(getter, setter);
    };
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @protected
   * @method
   */
  method: function(name) {
    return function(relation) {
      return function() {
        return relation[name](this, arguments);
      };
    };
  },

  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @public
   * @method
   */
  attribute: function() {
    return _.partial(RelationTrigger.create.bind(RelationTrigger), this);
  }

});

module.exports = BaseRelation.reopenClass({ __name__: 'BaseRelation' });
<|endoftext|>


<commit_before>/*
* That's the implementation of require-loader
*/

var fs = require('fs');
var util = require('util');

function ReqManager(options) {
    this.path = options.path || "./";
    this.isWatch = options.watch || true;
    this.map = [];
    this.resolve_names = [];
    this.onChange = options.listener || function() {};
}

ReqManager.prototype.setPath = function(path) {
    this.path = path;
}

// Add filename (module)
ReqManager.prototype.add = function(filename) {
    this.map[filename] = require(this.path + "/" + filename);
    this.resolve_names[filename] = require.resolve(this.path + "/" + filename);
    this.onChange(null, {action:'add', filename:filename, resolve_names:this.resolve_names[filename]});
    return this.map[filename];
}

// remove filename (module)
ReqManager.prototype.remove = function(filename) {
    var resolve_names = this.resolve_names[filename];
    delete require.cache[this.resolve_names[filename]];
    delete this.resolve_names[filename];
    delete this.map[filename];
    this.onChange(null, {action:'remove', filename:filename, resolve_names:resolve_names});
}

// return the require map;
ReqManager.prototype.getMap = function() {
    return this.map;
}

/*
* Initial module(s) include
*/
ReqManager.prototype.init = function() {
    // get all files from the directory
    var dir = fs.readdirSync(this.path);

    for (var i=0; i<dir.length; i++) {
        this.add(dir[i]);
    }

    if (this.isWatch) {
        this.watch();
    }
}

/*
* Watch changes in folder.
*/
ReqManager.prototype.watch = function() {
    var that = this;
    fs.watch(that.path, function(event, filename){
        console.log("Filename: " + filename);
        if (that.map[filename]) {
            // exist in map.  check if the file still exist.
            // if doesn't exist anymore, then remove from require cache.
            if (! fs.existsSync(that.path + "/" + filename)) {
                that.remove(filename);
            }
        } else {
            // add.
            that.add(filename);
        }
    });
}

/*
* Function to create the ReqManager object.
* options: {path: {String, default:'./'}, init: Boolean, onChange: function(err,data){}  }
*/
module.exports.create = function(options) {
    var requireManager = new ReqManager(options);
    if (options.init) {
        requireManager.init();
    }
    return requireManager;
}

<commit_msg>fix bug<commit_after>/*
* That's the implementation of require-loader
*/

var fs = require('fs');
var util = require('util');

function ReqManager(options) {
    this.path = options.path || "./";
    this.isWatch = options.watch || true;
    this.map = [];
    this.resolve_names = [];
    this.onChange = options.onChange || function() {};
}

ReqManager.prototype.setPath = function(path) {
    this.path = path;
}

// Add filename (module)
ReqManager.prototype.add = function(filename) {
    this.map[filename] = require(this.path + "/" + filename);
    this.resolve_names[filename] = require.resolve(this.path + "/" + filename);
    this.onChange(null, {action:'add', filename:filename, resolve_names:this.resolve_names[filename]});
    return this.map[filename];
}

// remove filename (module)
ReqManager.prototype.remove = function(filename) {
    var resolve_names = this.resolve_names[filename];
    delete require.cache[this.resolve_names[filename]];
    delete this.resolve_names[filename];
    delete this.map[filename];
    this.onChange(null, {action:'remove', filename:filename, resolve_names:resolve_names});
}

// return the require map;
ReqManager.prototype.getMap = function() {
    return this.map;
}

/*
* Initial module(s) include
*/
ReqManager.prototype.init = function() {
    // get all files from the directory
    var dir = fs.readdirSync(this.path);

    for (var i=0; i<dir.length; i++) {
        this.add(dir[i]);
    }

    if (this.isWatch) {
        this.watch();
    }
}

/*
* Watch changes in folder.
*/
ReqManager.prototype.watch = function() {
    var that = this;
    fs.watch(that.path, function(event, filename){
        if (that.map[filename]) {
            // exist in map.  check if the file still exist.
            // if doesn't exist anymore, then remove from require cache.
            if (! fs.existsSync(that.path + "/" + filename)) {
                that.remove(filename);
            }
        } else {
            // add.
            that.add(filename);
        }
    });
}

/*
* Function to create the ReqManager object.
* options: {path: {String, default:'./'}, init: Boolean, onChange: function(err,data){}  }
*/
module.exports.create = function(options) {
    var requireManager = new ReqManager(options);
    if (options.init) {
        requireManager.init();
    }
    return requireManager;
}

<|endoftext|>


<commit_before>var jsVariants = require('interpret').jsVariants,
    endsWith = require('lodash.endswith'),
    availableExtensions = Object.keys(jsVariants);

// sort extensions to ensure that .babel.js and
// similar ones are always matched before .js
availableExtensions.sort(function(a, b) {
    var res = -(a.split(/\./).length - b.split(/\./).length);
    // all things being equal, we need to
    // prioritize .js as it is most likely
    if(res === 0) {
        if(a === '.js') {
            return -1;
        }
        if(b === '.js') {
            return 1;
        }
        return 0;
    }
    return res;
});

function getMatchingLoader(configPath) {
    for(var i = 0, len = availableExtensions.length; i < len; i++) {
        var ext = availableExtensions[i];
        if(endsWith(configPath, ext)) {
            return jsVariants[ext];
        }
    }
    return null;
}

module.exports = function(configPath) {
    var mod = getMatchingLoader(configPath);
    if(mod) {
        var mods = Array.isArray(mod) ? mod : [mod],
            installed = false;

        for(var i = 0, len = mods.length; i < len; i++) {
            mod = mods[i];
            if(typeof mod === 'string') {
                try {
                    require(mod);
                    installed = true;
                } catch(ignored) {}
            } else if(typeof mod === 'object') {
                try {
                    var s = require(mod.module);
                    mod.register(s);
                    installed = true;
                } catch(ignored) {}
            }

            if(installed) {
                break;
            }
        }

        if(!installed) {
            throw new Error('Could not load required module loading for ' + chalk.underline(configPath));
        }
    }
    var config = require(configPath);
    if (typeof config === 'function')
        return config(
            process.argv.filter(function (arg) {
                return arg.slice(0, 6) === '--env.';
            }).map(function (arg) {
                var parts = arg.split('=');
                return [parts[0].slice(6), parts.slice(1).join('=')];
            }).reduce(function (env, pair) {
                env[pair[0]] = pair[1];
                return env;
            }, {})
        );
    return config;
}
<commit_msg>use minimist<commit_after>var jsVariants = require('interpret').jsVariants,
    endsWith = require('lodash.endswith'),
    availableExtensions = Object.keys(jsVariants);

// sort extensions to ensure that .babel.js and
// similar ones are always matched before .js
availableExtensions.sort(function(a, b) {
    var res = -(a.split(/\./).length - b.split(/\./).length);
    // all things being equal, we need to
    // prioritize .js as it is most likely
    if(res === 0) {
        if(a === '.js') {
            return -1;
        }
        if(b === '.js') {
            return 1;
        }
        return 0;
    }
    return res;
});

function getMatchingLoader(configPath) {
    for(var i = 0, len = availableExtensions.length; i < len; i++) {
        var ext = availableExtensions[i];
        if(endsWith(configPath, ext)) {
            return jsVariants[ext];
        }
    }
    return null;
}

module.exports = function(configPath) {
    var mod = getMatchingLoader(configPath);
    if(mod) {
        var mods = Array.isArray(mod) ? mod : [mod],
            installed = false;

        for(var i = 0, len = mods.length; i < len; i++) {
            mod = mods[i];
            if(typeof mod === 'string') {
                try {
                    require(mod);
                    installed = true;
                } catch(ignored) {}
            } else if(typeof mod === 'object') {
                try {
                    var s = require(mod.module);
                    mod.register(s);
                    installed = true;
                } catch(ignored) {}
            }

            if(installed) {
                break;
            }
        }

        if(!installed) {
            throw new Error('Could not load required module loading for ' + chalk.underline(configPath));
        }
    }
    var config = require(configPath);
    if (typeof config === 'function')
        return config(require('minimist')(process.argv, { '--': true }).env);
    return config;
}
<|endoftext|>


<commit_before>/* global window */
'use strict'

var win = typeof window === 'undefined' ? null : window

exports.routeFromLocation = function routeFromLocation (event, router) {
  router.route(win.location.href)
}

exports.routeFromLinkClick = function routeFromLinkClick (event, router) {
  // ignore if it could open a new window, if a right click
  if (
    event.metaKey || event.shiftKey || event.ctrlKey || event.altKey ||
    event.which === 3 || event.button === 2
  ) return

  // ignore if not a link click
  var html = win.document.documentElement
  var target = event.target
  while (target && !target.href && target !== html) {
    target = target.parentNode
  }
  if (!target || !target.href) return

  // ignore if not the same origin as the page
  var location = win.location
  var origin = location.origin || (location.protocol + '//' + location.host)
  if (target.href.slice(0, origin.length) !== origin) return

  event.preventDefault()
  var path = target.href.slice(origin.length)
  var hash = router.hash
  if (hash && path.indexOf(hash) >= 0) {
    path = path.slice(path.indexOf(hash) + hash.length)
  }
  router.navigate(path)
}
<commit_msg>check defaultPrevented when intercepting link clicks<commit_after>/* global window */
'use strict'

var win = typeof window === 'undefined' ? null : window

exports.routeFromLocation = function routeFromLocation (event, router) {
  router.route(win.location.href)
}

exports.routeFromLinkClick = function routeFromLinkClick (event, router) {
  // ignore if it could open a new window, if a right click
  if (
    event.metaKey || event.shiftKey || event.ctrlKey || event.altKey ||
    event.which === 3 || event.button === 2 || event.defaultPrevented
  ) return

  // ignore if not a link click
  var html = win.document.documentElement
  var target = event.target
  while (target && !target.href && target !== html) {
    target = target.parentNode
  }
  if (!target || !target.href) return

  // ignore if not the same origin as the page
  var location = win.location
  var origin = location.origin || (location.protocol + '//' + location.host)
  if (target.href.slice(0, origin.length) !== origin) return

  event.preventDefault()
  var path = target.href.slice(origin.length)
  var hash = router.hash
  if (hash && path.indexOf(hash) >= 0) {
    path = path.slice(path.indexOf(hash) + hash.length)
  }
  router.navigate(path)
}
<|endoftext|>


<commit_before>var _ = require('lodash');
var fs = require('fs');
var os = require('os');
var path = require('path');
var filesize = require('filesize');
var humanizeDuration = require('humanize-duration');
var auth = require('basic-auth');
var cssfile = path.resolve(__dirname, '../public/profile.css');
var layerimg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHdpZHRoPSIzMnB4IiBoZWlnaHQ9IjIycHgiIHZpZXdCb3g9IjAgMCAzMiAyMiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMzIgMjIiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGc+DQoJPGc+DQoJCTxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0xNiwybDE0LDUuNUwxNiwxMkwyLDcuNUwxNiwyIE0xNiwwYy0wLjIsMC0wLjUsMC0wLjcsMC4xbC0xNCw1LjVDMC41LDUuOSwwLDYuNywwLDcuNQ0KCQkJYzAsMC44LDAuNiwxLjYsMS40LDEuOGwxNCw0LjVDMTUuNiwxNCwxNS44LDE0LDE2LDE0YzAuMiwwLDAuNCwwLDAuNi0wLjFsMTQtNC41YzAuOC0wLjMsMS40LTEsMS40LTEuOGMwLTAuOC0wLjUtMS42LTEuMy0xLjkNCgkJCWwtMTQtNS41QzE2LjUsMCwxNi4zLDAsMTYsMEwxNiwweiIvPg0KCTwvZz4NCgk8Zz4NCgkJPHBhdGggZmlsbD0iI0ZGRkZGRiIgZD0iTTE2LDE4Yy0wLjEsMC0wLjIsMC0wLjMtMC4xbC0xNS01Yy0wLjUtMC4yLTAuOC0wLjctMC42LTEuM2MwLjItMC41LDAuNy0wLjgsMS4zLTAuNkwxNiwxNmwxNC43LTQuOQ0KCQkJYzAuNS0wLjIsMS4xLDAuMSwxLjMsMC42YzAuMiwwLjUtMC4xLDEuMS0wLjYsMS4zbC0xNSw1QzE2LjIsMTgsMTYuMSwxOCwxNiwxOHoiLz4NCgk8L2c+DQoJPGc+DQoJCTxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0xNiwyMmMtMC4xLDAtMC4yLDAtMC4zLTAuMWwtMTUtNWMtMC41LTAuMi0wLjgtMC43LTAuNi0xLjNjMC4yLTAuNSwwLjctMC44LDEuMy0wLjZMMTYsMjBsMTQuNy00LjkNCgkJCWMwLjUtMC4yLDEuMSwwLjEsMS4zLDAuNmMwLjIsMC41LTAuMSwxLjEtMC42LDEuM2wtMTUsNUMxNi4yLDIyLDE2LjEsMjIsMTYsMjJ6Ii8+DQoJPC9nPg0KPC9nPg0KPC9zdmc+DQo=';

module.exports = function(req, res, server) {
	if (process.env.TILESTRATA_PASSWORD) {
		var credentials = auth(req);
		if (!credentials || credentials.pass !== process.env.TILESTRATA_PASSWORD) {
			res.writeHead(401, {'WWW-Authenticate': 'Basic realm="tilestrata"'});
			res.write('Access denied');
			return res.end();
		}
	}

	var data = server.getProfileData();
	var zooms = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];
	var stageorder = {
		'reqhook': 1,
		'cache.get': 2,
		'provider': 3,
		'transform': 4,
		'reshook': 5,
		'cache.set': 6
	};

	if (/format=json/.test(req.url)) {
		var buffer = new Buffer(JSON.stringify(data), 'utf8');
		res.writeHead(200, {'Content-Length': buffer.length, 'Content-Type': 'application/json; charset=utf-8'});
		res.write(buffer);
		res.end();
	} else {
		fs.readFile(cssfile, 'utf8', function(err, css) {
			if (err) throw err;
			var html = [
				'',
				'
',
					' TileStrata Profile Data ',
					'(',
						'Host: ' + _.escape(os.hostname()) + ', ',
						'Uptime: ' + humanizeDuration(server.uptime().duration) + ', ',
						'Now: ' + (new Date()).toISOString() + ')',
					'',
				'
'
			];
			var layers = Object.keys(data);
			layers.sort();

			layers.forEach(function(layer) {
				html.push('
'+layer+'
');
				var routes = Object.keys(data[layer]);
				routes.sort();
				html.push('
');
				routes.forEach(function(route) {
					html.push('
'+route+'	');
					zooms.forEach(function(z) {
						html.push('z'+z+'	');
					});
					html.push('
');

					var plugins = Object.keys(data[layer][route]);
					plugins.sort(function(a,b) {
						var stage_a = stageorder[a.replace(/#\d+/,'')];
						var stage_b = stageorder[b.replace(/#\d+/,'')];
						return stage_a - stage_b;
					});
					plugins.forEach(function(plugin) {
						var plugin_name = data[layer][route][plugin].plugin_name;
						var plugin_type = plugin.replace(/#\d+/,'').replace(/\./, '-');
						var fields_available = [];
						if (plugin_name) plugin_name = '
' + _.escape(plugin_name) + '';
						Object.keys(data[layer][route][plugin].zooms).forEach(function(z) {
							fields_available = _.union(Object.keys(data[layer][route][plugin].zooms[z]));
						});

						fields_available.forEach(function(field, i) {
							html.push('
');
							if (i === 0) html.push(''+plugin+plugin_name+'	');
							html.push(''+field+'	');
							var strong_start = /avg/.test(field) ? '' : '';
							var strong_end = /avg/.test(field) ? '' : '';
							zooms.forEach(function(z) {
								try {
									var class_attr = '';
									var val = Math.round(data[layer][route][plugin].zooms['z'+z][field]*10)/10;
									if (isNaN(val)) throw new Error('Not a number');
									if (/size/.test(field) && !/samples/.test(field)) val = filesize(val).replace(' ', '');
									if (field === 'dur_avg') {
										if (val > 500) class_attr = ' class="warn"';
										if (val > 1000) class_attr = ' class="critical"';
									}
									html.push(''+strong_start+val+strong_end+'	');
								}
								catch(e) { html.push('	'); }
							});
							html.push('
');
						});
					});
				});
				html.push('
');
			});

			var buffer = new Buffer(html.join(''), 'utf8');
			res.writeHead(200, {'Content-Length': buffer.length, 'Content-Type': 'text/html; charset=utf-8'});
			res.write(buffer);
			res.end();
		});
	}
};
<commit_msg>Sort profile table fields for better readability<commit_after>var _ = require('lodash');
var fs = require('fs');
var os = require('os');
var path = require('path');
var filesize = require('filesize');
var humanizeDuration = require('humanize-duration');
var auth = require('basic-auth');
var cssfile = path.resolve(__dirname, '../public/profile.css');
var layerimg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHdpZHRoPSIzMnB4IiBoZWlnaHQ9IjIycHgiIHZpZXdCb3g9IjAgMCAzMiAyMiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMzIgMjIiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGc+DQoJPGc+DQoJCTxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0xNiwybDE0LDUuNUwxNiwxMkwyLDcuNUwxNiwyIE0xNiwwYy0wLjIsMC0wLjUsMC0wLjcsMC4xbC0xNCw1LjVDMC41LDUuOSwwLDYuNywwLDcuNQ0KCQkJYzAsMC44LDAuNiwxLjYsMS40LDEuOGwxNCw0LjVDMTUuNiwxNCwxNS44LDE0LDE2LDE0YzAuMiwwLDAuNCwwLDAuNi0wLjFsMTQtNC41YzAuOC0wLjMsMS40LTEsMS40LTEuOGMwLTAuOC0wLjUtMS42LTEuMy0xLjkNCgkJCWwtMTQtNS41QzE2LjUsMCwxNi4zLDAsMTYsMEwxNiwweiIvPg0KCTwvZz4NCgk8Zz4NCgkJPHBhdGggZmlsbD0iI0ZGRkZGRiIgZD0iTTE2LDE4Yy0wLjEsMC0wLjIsMC0wLjMtMC4xbC0xNS01Yy0wLjUtMC4yLTAuOC0wLjctMC42LTEuM2MwLjItMC41LDAuNy0wLjgsMS4zLTAuNkwxNiwxNmwxNC43LTQuOQ0KCQkJYzAuNS0wLjIsMS4xLDAuMSwxLjMsMC42YzAuMiwwLjUtMC4xLDEuMS0wLjYsMS4zbC0xNSw1QzE2LjIsMTgsMTYuMSwxOCwxNiwxOHoiLz4NCgk8L2c+DQoJPGc+DQoJCTxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0xNiwyMmMtMC4xLDAtMC4yLDAtMC4zLTAuMWwtMTUtNWMtMC41LTAuMi0wLjgtMC43LTAuNi0xLjNjMC4yLTAuNSwwLjctMC44LDEuMy0wLjZMMTYsMjBsMTQuNy00LjkNCgkJCWMwLjUtMC4yLDEuMSwwLjEsMS4zLDAuNmMwLjIsMC41LTAuMSwxLjEtMC42LDEuM2wtMTUsNUMxNi4yLDIyLDE2LjEsMjIsMTYsMjJ6Ii8+DQoJPC9nPg0KPC9nPg0KPC9zdmc+DQo=';
var field_order = ['errors', 'hits', 'misses', 'dur_min', 'dur_avg', 'dur_max', 'dur_samples', 'size_min', 'size_avg', 'size_max', 'size_samples'];

module.exports = function(req, res, server) {
	if (process.env.TILESTRATA_PASSWORD) {
		var credentials = auth(req);
		if (!credentials || credentials.pass !== process.env.TILESTRATA_PASSWORD) {
			res.writeHead(401, {'WWW-Authenticate': 'Basic realm="tilestrata"'});
			res.write('Access denied');
			return res.end();
		}
	}

	var data = server.getProfileData();
	var zooms = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];
	var stageorder = {
		'reqhook': 1,
		'cache.get': 2,
		'provider': 3,
		'transform': 4,
		'reshook': 5,
		'cache.set': 6
	};

	if (/format=json/.test(req.url)) {
		var buffer = new Buffer(JSON.stringify(data), 'utf8');
		res.writeHead(200, {'Content-Length': buffer.length, 'Content-Type': 'application/json; charset=utf-8'});
		res.write(buffer);
		res.end();
	} else {
		fs.readFile(cssfile, 'utf8', function(err, css) {
			if (err) throw err;
			var html = [
				'',
				'
',
					' TileStrata Profile Data ',
					'(',
						'Host: ' + _.escape(os.hostname()) + ', ',
						'Uptime: ' + humanizeDuration(server.uptime().duration) + ', ',
						'Now: ' + (new Date()).toISOString() + ')',
					'',
				'
'
			];
			var layers = Object.keys(data);
			layers.sort();

			layers.forEach(function(layer) {
				html.push('
'+layer+'
');
				var routes = Object.keys(data[layer]);
				routes.sort();
				html.push('
');
				routes.forEach(function(route) {
					html.push('
'+route+'	');
					zooms.forEach(function(z) {
						html.push('z'+z+'	');
					});
					html.push('
');

					var plugins = Object.keys(data[layer][route]);
					plugins.sort(function(a,b) {
						var stage_a = stageorder[a.replace(/#\d+/,'')];
						var stage_b = stageorder[b.replace(/#\d+/,'')];
						return stage_a - stage_b;
					});
					plugins.forEach(function(plugin) {
						var plugin_name = data[layer][route][plugin].plugin_name;
						var plugin_type = plugin.replace(/#\d+/,'').replace(/\./, '-');
						var fields_available = [];
						if (plugin_name) plugin_name = '
' + _.escape(plugin_name) + '';
						Object.keys(data[layer][route][plugin].zooms).forEach(function(z) {
							fields_available = _.union(Object.keys(data[layer][route][plugin].zooms[z]));
						});

						fields_available.sort(function(a, b) {
							return field_order.indexOf(a) - field_order.indexOf(b);
						});

						fields_available.forEach(function(field, i) {
							html.push('
');
							if (i === 0) html.push(''+plugin+plugin_name+'	');
							html.push(''+field+'	');
							var strong_start = /avg/.test(field) ? '' : '';
							var strong_end = /avg/.test(field) ? '' : '';
							zooms.forEach(function(z) {
								try {
									var class_attr = '';
									var val = Math.round(data[layer][route][plugin].zooms['z'+z][field]*10)/10;
									if (isNaN(val)) throw new Error('Not a number');
									if (/size/.test(field) && !/samples/.test(field)) val = filesize(val).replace(' ', '');
									if (field === 'dur_avg') {
										if (val > 500) class_attr = ' class="warn"';
										if (val > 1000) class_attr = ' class="critical"';
									}
									html.push(''+strong_start+val+strong_end+'	');
								}
								catch(e) { html.push('	'); }
							});
							html.push('
');
						});
					});
				});
				html.push('
');
			});

			var buffer = new Buffer(html.join(''), 'utf8');
			res.writeHead(200, {'Content-Length': buffer.length, 'Content-Type': 'text/html; charset=utf-8'});
			res.write(buffer);
			res.end();
		});
	}
};
<|endoftext|>


<commit_before>ProfileController = RouteController.extend({
  subscriptions: function () {
    return [
      subs.subscribe('userProfile', this.params._id),
      Meteor.subscribe('userComments', this.params._id, Session.get('itemsLimit')),
      Meteor.subscribe('userTopics', this.params._id, Session.get('itemsLimit'))
    ];
  },
  onRun: function () {
    var query = this.params.query;
    var tabs = {
      'comments': 'profileComments',
      'topics': 'profileTopics',
      'followers': 'profileFollowers',
      'following': 'profileFollowing'
    };

    Session.set('itemsLimit', 15);
    Session.set('currentTab', tabs[query.tab] || 'profileComments');
    console.log('onRun for profile route');
    this.next();
  },
  action: function () {
    if (this.ready() && Meteor.user()) {
      this.render();
      this.render('nav', { to: 'nav' });
      this.render('profileButtons', { to: 'pageButtons' });
      this.render('profileHeader', { to: 'pageHeader' });
      this.render('profileNav', { to: 'pageNav' });
    }
    this.next();
  },
  data: function () {
    return Meteor.users.findOne(this.params._id);
  }
});

Router.route('/users/:_id', {
  name: 'profile',
  controller: ProfileController,
  // fastRender: true
});<commit_msg>FastRender support for profile<commit_after>ProfileController = RouteController.extend({
  subscriptions: function () {
    var limit = 15;
    if (Meteor.isClient) {
      limit = Session.get('itemsLimit');
    }

    return [
      subs.subscribe('userProfile', this.params._id),
      Meteor.subscribe('userComments', this.params._id, limit),
      Meteor.subscribe('userTopics', this.params._id, limit)
    ];
  },
  onRun: function () {
    var query = this.params.query;
    var tabs = {
      'comments': 'profileComments',
      'topics': 'profileTopics',
      'followers': 'profileFollowers',
      'following': 'profileFollowing'
    };

    Session.set('itemsLimit', 15);
    Session.set('currentTab', tabs[query.tab] || 'profileComments');
    console.log('onRun for profile route');
    this.next();
  },
  action: function () {
    if (this.ready() && Meteor.user()) {
      this.render();
      this.render('nav', { to: 'nav' });
      this.render('profileButtons', { to: 'pageButtons' });
      this.render('profileHeader', { to: 'pageHeader' });
      this.render('profileNav', { to: 'pageNav' });
    }
    this.next();
  },
  data: function () {
    return Meteor.users.findOne(this.params._id);
  },
  fastRender: true
});

Router.route('/users/:_id', {
  name: 'profile',
  controller: ProfileController
});<|endoftext|>


<commit_before>'use strict';

var debug = require('debug')('sphere:modelstore');
var when = require('when');
var errors = require('./errors');
var Joi = require('joi');

var VALID_MODELS = ['room', 'thing'];

var UserSchema = Joi.object().keys({id: Joi.string().token()});
var NodeIdSchema = Joi.string().token();

module.exports.calculateSyncItems = function(user, nodeId, modelName, nodeManifest) {
  Joi.assert(user, UserSchema);
  Joi.assert(nodeId, NodeIdSchema);
  Joi.assert(modelName, Joi.string().valid(VALID_MODELS));
  Joi.assert(nodeManifest, Joi.object());

  var query = {
    key: [user.id, modelName]
  };
  return this.couchdb.view('manifest/manifest', query).then(function(result) {
    var cloudManifest = _makeManifest(result);
    var cloudNewerItems = _findGreaterItems(cloudManifest, nodeManifest);
    var nodeNewerItems = _findGreaterItems(nodeManifest, cloudManifest);

    var response = {
      model: modelName,
      cloud_requires: nodeNewerItems,
      node_requires: cloudNewerItems
    };

    return response;
  });
};

module.exports.doSyncItems = function(user, nodeId, modelName, pushedItems, requestedObjectIds) {
  Joi.assert(user, UserSchema);
  Joi.assert(nodeId, NodeIdSchema);
  Joi.assert(modelName, Joi.string().valid(VALID_MODELS));
  Joi.assert(requestedObjectIds, Joi.array().includes(Joi.string().token()));
  Joi.assert(pushedItems, Joi.object());

  // retrieve the requested objects

  var query = {
    keys: [],
    include_docs: true
  };

  requestedObjectIds.forEach(function(v) {
    Joi.assert(v, Joi.string().token());
    query.keys.push([user.id, modelName, v]);
  });

  var responseItems = this.couchdb.view('manifest/manifest', query).then(function(result) {
    var resultMap = {};

    result.rows.map(function(row) {
      resultMap[row.doc.model.id] = row.doc;
    });

    return resultMap;
  });

  // update the objects provided by the node
  var toSave = [];

  var existingIds = Object.keys(pushedItems).map(function(objectId) {
    return [user.id, modelName, objectId].join(':');
  });

  var savePromise = this.couchdb.getAll(existingIds).then(function(result) {
    var oldDocLookup = {};
    result.forEach(function(doc) {
      oldDocLookup[doc._id] = doc;
    });

    for (var objectId in pushedItems) {
      var object = pushedItems[objectId];

      Joi.assert(objectId, Joi.string().token());
      Joi.assert(object, Joi.object().keys({ last_modified: Joi.number(), data: Joi.object() }));

      var newDocument = {
        _id: [user.id, modelName, objectId].join(':'),
        user: user,
        model: {
          type: modelName,
          id: objectId,
        },
        data: object.data,
        last_modified: object.last_modified,
        last_updated_by: {
          node: nodeId,
        }
      };

      if (oldDocLookup.hasOwnProperty(newDocument._id)) {
        var oldDoc = oldDocLookup[newDocument._id];
        if (oldDoc.last_modified < newDocument.last_modified) {
          newDocument._rev = oldDoc._rev;
        } else {
          continue; // skip this document, it's been updated in cloud in the meantime
        }
      }

      toSave.push(newDocument);
    }

    if (toSave.length > 0) {
      return this.couchdb.saveAll(toSave);
    }
  }.bind(this));

  // merge for response

  return when.all([
    responseItems,
    savePromise,
  ]).spread(function(requestedObjects, saveResponse) {
    var pushedObjects = {};

    if (saveResponse) {
      saveResponse.forEach(function(doc) {
        pushedObjects[doc.data.id] = (typeof doc._rev === 'string')
      });
    }

    return {
      model: modelName,
      requestedObjects: requestedObjects,
      pushedObjects: pushedObjects
    };
  });
};

function _makeManifest(result) {
  var manifest = {};

  result.rows.forEach(function(row) {
    manifest[row.value.id] = row.value.last_modified;
  });

  return manifest;
}

function _findGreaterItems(src, dst) {
  var greater = {};

  for (var k in src) {
    var sv = src[k];
    var dv = dst[k];

    if (!dv || dv < sv) {
      greater[k] = sv;
    }
  }

  return greater;
}<commit_msg>Don't use node ids, since we don't have them.<commit_after>'use strict';

var debug = require('debug')('sphere:modelstore');
var when = require('when');
var errors = require('./errors');
var Joi = require('joi');

var VALID_MODELS = ['room', 'thing'];

var UserSchema = Joi.object().keys({id: Joi.string().token()});

module.exports.calculateSyncItems = function(user, modelName, nodeManifest) {
  Joi.assert(user, UserSchema);
  Joi.assert(modelName, Joi.string().valid(VALID_MODELS));
  Joi.assert(nodeManifest, Joi.object());

  var query = {
    key: [user.id, modelName]
  };
  return this.couchdb.view('manifest/manifest', query).then(function(result) {
    var cloudManifest = _makeManifest(result);
    var cloudNewerItems = _findGreaterItems(cloudManifest, nodeManifest);
    var nodeNewerItems = _findGreaterItems(nodeManifest, cloudManifest);

    var response = {
      model: modelName,
      cloud_requires: nodeNewerItems,
      node_requires: cloudNewerItems
    };

    return response;
  });
};

module.exports.doSyncItems = function(user, modelName, pushedItems, requestedObjectIds) {
  Joi.assert(user, UserSchema);
  Joi.assert(modelName, Joi.string().valid(VALID_MODELS));
  Joi.assert(requestedObjectIds, Joi.array().includes(Joi.string().token()));
  Joi.assert(pushedItems, Joi.object());

  // retrieve the requested objects

  var query = {
    keys: [],
    include_docs: true
  };

  requestedObjectIds.forEach(function(v) {
    Joi.assert(v, Joi.string().token());
    query.keys.push([user.id, modelName, v]);
  });

  var responseItems = this.couchdb.view('manifest/manifest', query).then(function(result) {
    var resultMap = {};

    result.rows.map(function(row) {
      resultMap[row.doc.model.id] = row.doc;
    });

    return resultMap;
  });

  // update the objects provided by the node
  var toSave = [];

  var existingIds = Object.keys(pushedItems).map(function(objectId) {
    return [user.id, modelName, objectId].join(':');
  });

  var savePromise = this.couchdb.getAll(existingIds).then(function(result) {
    var oldDocLookup = {};
    result.forEach(function(doc) {
      oldDocLookup[doc._id] = doc;
    });

    for (var objectId in pushedItems) {
      var object = pushedItems[objectId];

      Joi.assert(objectId, Joi.string().token());
      Joi.assert(object, Joi.object().keys({ last_modified: Joi.number(), data: Joi.object() }));

      var newDocument = {
        _id: [user.id, modelName, objectId].join(':'),
        user: user,
        model: {
          type: modelName,
          id: objectId,
        },
        data: object.data,
        last_modified: object.last_modified,
      };

      if (oldDocLookup.hasOwnProperty(newDocument._id)) {
        var oldDoc = oldDocLookup[newDocument._id];
        if (oldDoc.last_modified < newDocument.last_modified) {
          newDocument._rev = oldDoc._rev;
        } else {
          continue; // skip this document, it's been updated in cloud in the meantime
        }
      }

      toSave.push(newDocument);
    }

    if (toSave.length > 0) {
      return this.couchdb.saveAll(toSave);
    }
  }.bind(this));

  // merge for response

  return when.all([
    responseItems,
    savePromise,
  ]).spread(function(requestedObjects, saveResponse) {
    var pushedObjects = {};

    if (saveResponse) {
      saveResponse.forEach(function(doc) {
        pushedObjects[doc.data.id] = (typeof doc._rev === 'string')
      });
    }

    return {
      model: modelName,
      requestedObjects: requestedObjects,
      pushedObjects: pushedObjects
    };
  });
};

function _makeManifest(result) {
  var manifest = {};

  result.rows.forEach(function(row) {
    manifest[row.value.id] = row.value.last_modified;
  });

  return manifest;
}

function _findGreaterItems(src, dst) {
  var greater = {};

  for (var k in src) {
    var sv = src[k];
    var dv = dst[k];

    if (!dv || dv < sv) {
      greater[k] = sv;
    }
  }

  return greater;
}<|endoftext|>


<commit_before>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You 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 fs = require('fs');
var path = require('path');
var Buffer = require('buffer').Buffer;
var log = require('util/log');
var msic = require('util/misc');
var async = require('extern/async');
var jspack = require('extern/jspack/jspack').jspack;

var RUNSV_TEMPLATE = {
  run: "#!/bin/bash\n# Stub run file\nexit 0",
  finish: "#!/bin/bash\n# Stubbed out finish file\nexit 0;",
  down: "# Down file so it doesn't start up automagically",
  log: {
    "run": "#!/bin/bash\necho 'start'",
    "finish": "#!/bin/bash\necho 'finish'"
  }
};

/**
 * RunitService represents a runit service control directory (as passed to
 * runsv).  These are lazily constructed, so its possible that a RunitService's
 * doesn't corresponding directory doesn't actually exist, and you won't know
 * until you attempt to read the details, etc.
 *
 * @param {String} basedir  The directory in which the service resides
 * @param {String} name     The name of the service, corresponds to the name of
 *                            the service's control directory.
 */
function RunitService(basedir, name) {
  this.basedir = basedir;
  this.name = name;
}

/**
 * Reads the status file of a RunitService and retrieve an object containing:
 *    'name': The name of the service
 *    'time': The time the service was started
 *    'pid': The last known PID of the service, or -1 if it is unknown
 *    'normally: "up" if the service is auto-started, otherwise "down"
 *    'paused': A boolean representing whether the service is paused
 *    'want': "up" if the service is designated as running, otherwise "down"
 *    'term': A boolean representing whether the service was sent TERM
 *    'state': "down", "run" or "finish" depending on the current state
 *
 * Potential errors and the details object are passed to a required callback
 *
 * @param {Function} callback A required callback taking (err, details).
 */
RunitService.prototype.get_details = function(callback) {
  var details = {};
  var err;
  var dir = path.join(this.basedir, this.name);
  var ctrl_path = path.join(dir, "supervise", "status");
  var down_path = path.join(dir, "supervise", "down");
  path.exists(ctrl_path, function(exists) {
    if (!exists) {
      err = new Error("Couldn't find supervise/status file");
      return callback(err, details);
    }
    else {
      fs.open(ctrl_path, "r", 0644, function(_err, fd) {
        if (_err) {
          return callback(_err, details);
        }
        path.exists(down_path, function(exists) {
          var normallyup = (!exists);
          var buf = new Buffer(1024);
          /**
           * The 'status' file binary format is:
           *   Start time is stored as:
           *     Seconds in a uint64_t in indices 0 - 7
           *     Nanoseconds in an unsigned long in indices 8 - 11
           *   PID packed in indices 12 - 15
           *   Paused is 0|1 at index 16
           *   Want is u|d at index 17
           *   TERM is 0|1 at index 18
           *   State is (0|1|2) = (down|run|finish) at index 19
           */
          fs.read(fd, buf, 0, buf.length, null, function(_err, bytesRead) {
            if (_err) {
              return callback(_err, details);
            }
            var time = jspack.Unpack('>L', buf, 4)[0];
            var pid = jspack.Unpack('<L', buf, 12)[0];
            var paused = buf[16];
            var want = buf[17];
            var term = buf[18];
            var state = buf[19];
            details.name = this.name;
            details.time = jspack.Unpack('>L>L', buf, 0)[1];
            details.pid = (pid !== 0)? pid: -1;
            details.normally = normallyup? "up" : "down";
            details.paused = paused? true: false;
            details.want = {
              'u': "up",
              'd': "down"
            }[want];
            details.term = term? true:false;
            details.state = {
              0: "down",
              1: "run",
              2: "finish"
            }[state];
            return callback(err, details);
          });
        });
      });
    }
  });
};

/**
 * RunitServiceDirectory represents a runit services directory as passed to
 * 'runsvdir'. This is lazily constructed, so the success of this constructor
 * does not necessarily indicate that the directory exists or contains any
 * services.
 *
 * @param {String} dir  The path to the services directory
 */
function RunitServiceDirectory(dir) {
  this.dir = dir;
}

/**
 * Retrieve a service within the service directory by name. This takes a
 * required callback which will receive a possible error and the RunitService
 * object (which may not represent a valid service, see {@link RunitService}).
 *
 * @param {Function} cb A callback taking an error and a {@link RunitService}
 */
RunitServiceDirectory.prototype.get_service = function(name, callback) {
  var self = this;
  fs.stat(path.join(self.dir, name), function(err, stats) {
    if (err) {
      // If this happens, something is very wrong
      log.warn(err);
      return callack(err);
    }
    else {
      return callback(null, new RunitService(self.dir, name));
    }
  });
};

/**
 * Retrieve a list of objects containing details for all valid services in the
 * service directory.
 *
 * @param {Function} cb A callback taking an error a list of retrieved details
 */
RunitServiceDirectory.prototype.list_services_details = function(cb) {
  var self = this;
  var services = [];

  fs.readdir(self.dir, function(err, files) {
    // If the services directory can't be read, just return error now
    if (err) {
      return cb(err);
    }

    async.forEach(files, function(file, callback) {
      self.get_service(file, function(err, service) {
        if (err) {
          return callback(err);
        }
        service.get_details(function(err, details) {
          if (!err) {
            services.push(details);
          }
          return callback(err);
        });
      });
    },
    function(err) {
      cb(err, services);
    });
  });
};

/**
 * Create a RunitService layout with the given name. This is incomplete.
 *
 * @param {Function} cb A callback taking a possible error.
 */
RunitServiceDirectory.prototype.create_service_layout = function(name, cb) {
  var self = this;
  fs.stat(path.join(self.dir, name), function(err, stats) {
    if (!err) {
      cb(new Error("Service name already in use"));
    }
    else {
      misc.template_to_tree(dir, RUNSV_TEMPLATE, cb);
    }
  });
};

exports.RunitServiceDirectory = RunitServiceDirectory;
<commit_msg>Untested service starting, stopping, etc<commit_after>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You 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 fs = require('fs');
var path = require('path');
var Buffer = require('buffer').Buffer;
var log = require('util/log');
var msic = require('util/misc');
var async = require('extern/async');
var jspack = require('extern/jspack/jspack').jspack;

var RUNSV_TEMPLATE = {
  run: "#!/bin/bash\n# Stub run file\nexit 0",
  finish: "#!/bin/bash\n# Stubbed out finish file\nexit 0;",
  down: "# Down file so it doesn't start up automagically",
  log: {
    "run": "#!/bin/bash\necho 'start'",
    "finish": "#!/bin/bash\necho 'finish'"
  }
};

/**
 * RunitService represents a runit service control directory (as passed to
 * runsv).  These are lazily constructed, so its possible that a RunitService's
 * doesn't corresponding directory doesn't actually exist, and you won't know
 * until you attempt to read the details, etc.
 *
 * @param {String} basedir  The directory in which the service resides
 * @param {String} name     The name of the service, corresponds to the name of
 *                            the service's control directory.
 */
function RunitService(basedir, name) {
  this.basedir = basedir;
  this.name = name;
}

/**
 * Reads the status file of a RunitService and retrieve an object containing:
 *    'name': The name of the service
 *    'time': The time the service was started
 *    'pid': The last known PID of the service, or -1 if it is unknown
 *    'normally: "up" if the service is auto-started, otherwise "down"
 *    'paused': A boolean representing whether the service is paused
 *    'want': "up" if the service is designated as running, otherwise "down"
 *    'term': A boolean representing whether the service was sent TERM
 *    'state': "down", "run" or "finish" depending on the current state
 *
 * Potential errors and the details object are passed to a required callback
 *
 * @param {Function} callback A required callback taking (err, details).
 */
RunitService.prototype.get_details = function(callback) {
  var details = {};
  var err;
  var dir = path.join(this.basedir, this.name);
  var ctrl_path = path.join(dir, "supervise", "status");
  var down_path = path.join(dir, "supervise", "down");
  path.exists(ctrl_path, function(exists) {
    if (!exists) {
      err = new Error("Couldn't find supervise/status file");
      return callback(err, details);
    }
    else {
      fs.open(ctrl_path, "r", 0644, function(_err, fd) {
        if (_err) {
          return callback(_err, details);
        }
        path.exists(down_path, function(exists) {
          var normallyup = (!exists);
          var buf = new Buffer(1024);
          /**
           * The 'status' file binary format is:
           *   Start time is stored as:
           *     Seconds in a uint64_t in indices 0 - 7
           *     Nanoseconds in an unsigned long in indices 8 - 11
           *   PID packed in indices 12 - 15
           *   Paused is 0|1 at index 16
           *   Want is u|d at index 17
           *   TERM is 0|1 at index 18
           *   State is (0|1|2) = (down|run|finish) at index 19
           */
          fs.read(fd, buf, 0, buf.length, null, function(_err, bytesRead) {
            if (_err) {
              return callback(_err, details);
            }
            var time = jspack.Unpack('>L', buf, 4)[0];
            var pid = jspack.Unpack('<L', buf, 12)[0];
            var paused = buf[16];
            var want = buf[17];
            var term = buf[18];
            var state = buf[19];
            details.name = this.name;
            details.time = jspack.Unpack('>L>L', buf, 0)[1];
            details.pid = (pid !== 0)? pid: -1;
            details.normally = normallyup? "up" : "down";
            details.paused = paused? true: false;
            details.want = {
              'u': "up",
              'd': "down"
            }[want];
            details.term = term? true:false;
            details.state = {
              0: "down",
              1: "run",
              2: "finish"
            }[state];
            return callback(err, details);
          });
        });
      });
    }
  });
};

/**
 * Pipe characters into the runsv control pipe to control the service. For a
 * list of available control characters and their corresponding signals, see
 * the runsv man page.
 *
 * @param {String} cchar The control character to write to the pipe.
 * @param {Function} cb A callback called with a possible error
 */
RunitService.prototype.control = function(cchar, cb) {
  var cpath = path.join(this.dir, this.name, 'supervise', 'control');
  fs.open(cpath, 'a', function(err, fd) {
    if (err) {
      return cb(err);
    }
    fs.write(fd, cchar, 'ascii', function(err, writen) {
      return cb(err);
    });
  });
}

/**
 * Restart the service. The callback fires when the control characters have
 * been written, without regard to what actually happens to the service. This
 * sends a TERM followed by a CONT, then has runsv start the service and set it
 * to up.
 *
 * @param {Function} cb A callback called with a possible error
 */
RunitService.prototype.restart = function(cb) {
  this.control('tcu', cb);
}

/**
 * Start the service and set it to "up".
 *
 * @param {Function} cb A callback called with a possible error
 */
RunitService.prototype.start = function(cb) {
  this.control('u', cb);
}

/**
 * Stop the service and set it to "down".
 *
 * @param {Function} cb A callback called with a possible error
 */
RunitService.prototype.stop = function(cb) {
  this.control('d', cb);
}

/**
 * RunitServiceDirectory represents a runit services directory as passed to
 * 'runsvdir'. This is lazily constructed, so the success of this constructor
 * does not necessarily indicate that the directory exists or contains any
 * services.
 *
 * @param {String} dir  The path to the services directory
 */
function RunitServiceDirectory(dir) {
  this.dir = dir;
}

/**
 * Retrieve a service within the service directory by name. This takes a
 * required callback which will receive a possible error and the RunitService
 * object (which may not represent a valid service, see {@link RunitService}).
 *
 * @param {Function} cb A callback taking an error and a {@link RunitService}
 */
RunitServiceDirectory.prototype.get_service = function(name, callback) {
  var self = this;
  fs.stat(path.join(self.dir, name), function(err, stats) {
    if (err) {
      // If this happens, something is very wrong
      log.warn(err);
      return callack(err);
    }
    else {
      return callback(null, new RunitService(self.dir, name));
    }
  });
};

/**
 * Retrieve a list of objects containing details for all valid services in the
 * service directory.
 *
 * @param {Function} cb A callback taking an error a list of retrieved details
 */
RunitServiceDirectory.prototype.list_services_details = function(cb) {
  var self = this;
  var services = [];

  fs.readdir(self.dir, function(err, files) {
    // If the services directory can't be read, just return error now
    if (err) {
      return cb(err);
    }

    async.forEach(files, function(file, callback) {
      self.get_service(file, function(err, service) {
        if (err) {
          return callback(err);
        }
        service.get_details(function(err, details) {
          if (!err) {
            services.push(details);
          }
          return callback(err);
        });
      });
    },
    function(err) {
      cb(err, services);
    });
  });
};

/**
 * Create a RunitService layout with the given name. This is incomplete.
 *
 * @param {Function} cb A callback taking a possible error.
 */
RunitServiceDirectory.prototype.create_service_layout = function(name, cb) {
  var self = this;
  fs.stat(path.join(self.dir, name), function(err, stats) {
    if (!err) {
      cb(new Error("Service name already in use"));
    }
    else {
      misc.template_to_tree(dir, RUNSV_TEMPLATE, cb);
    }
  });
};

exports.RunitServiceDirectory = RunitServiceDirectory;
<|endoftext|>