<commit_before>'use strict';

/**
 * Class to coordinate work together
 */
function AntipodesMaps(opts) {
  this.opts = opts;
  this.verbose = opts.verbose != null || false;
  var ctx = this;

  // http://vehrka.cartodb.com/api/v2/viz/9fede618-6e3d-11e4-8fc1-0e853d047bba/viz.json

  $.ajax({
    url: 'http://'+ this.opts.cartodb.user + '.cartodb.com/api/v2/viz/' + this.opts.cartodb.viz + '/viz.json',
    contentType: 'text/plain',
    xhrFields: {
      withCredentials: false
    },
    dataType: "jsonp"
  }).then(function (response){
    if (ctx.verbose){
      alertify.success("Data visualization configuration loaded!");
    }
    // Configure map options with CartoDB Response
    var layers = response.layers[1].options.layer_definition.layers;
    var esData = layers.filter(function(l){
        return l.options.layer_name === opts.left.properties.layername;
      });
    var nzData = layers.filter(function(l){
        return l.options.layer_name === opts.right.properties.layername
      });

    if (esData.length == 1 && nzData.length == 1){
      opts.left.cartodb = esData[0].options;
      opts.right.cartodb = nzData[0].options;
    }

    ctx.setUpMaps(opts);
  });
}

AntipodesMaps.prototype.setUpMaps = function(opts) {
    this.leftMap =  new AntipodeMap(opts.center,opts.left,this);
    this.rightMap = this.leftMap.getAntipode(opts.right);
    this.schools = {
      "es":{},
      "nz":{}
    };

    this.setUpTriggers(this.leftMap);

    // Set up the central cross position
    var mapwidth = parseInt($('.map').css('width').replace('px',''));
    var crosswidth = parseInt($('.center-cross').css('width').replace('px',''));
    var leftCross = (mapwidth - crosswidth) / 2;

    $('.center-cross').css('left',leftCross + 'px');
};

AntipodesMaps.prototype.setUpTriggers = function(antipodeMap){
  var map = antipodeMap.map;
  var ctx = this;

  map.on('moveend',function(event){

    var now = new Date();
    var doIt = false;

    if (! ctx.lastDistSQL){
      ctx.lastDistSQL = now;
      doIt = true;
    } else if (ctx.lastDistSQL && (now - ctx.lastDistSQL) > 2000 ){
      doIt = true;
    }

    if (doIt){
      var center = ol.proj.transform(this.getView().getCenter(),'EPSG:3857','EPSG:4326');

      var distSQL = 'SELECT cod_es, cod_nz, dist, tunn FROM gvlc_getschools(st_geomfromtext(\'POINT('
        + center[0] + ' ' + center[1] + ')\'))';

      ctx.sqlLoader(distSQL).then(
        function(response){
          if (ctx.verbose){
            alertify.success("Distance between schools retreived");
          }
          var result = response.rows[0];
          ctx.updateDist(result);
        }, function(error){
          msgError("Error obtaining distance of schools",error,ctx.verbose);
        }
      );

      ctx.lastDistSQL = new Date();
    }

  });
}

AntipodesMaps.prototype.sqlLoader = function(sql) {
  return $.ajax({
    url: 'https://'+ this.opts.cartodb.user + '.cartodb.com/api/v2/sql?q=' + encodeURIComponent(sql),
    contentType: 'text/plain',
    xhrFields: {
      withCredentials: false
    },
    dataType: "jsonp"
  });
}

AntipodesMaps.prototype.updateDist = function(distData) {
  var ctx = this;

  function direction(from,to){
    var iY = to[1] - from[1];
    var iX = to[0] - from[0];
    var res = Math.atan2(iX,iY).toDeg();
    return res < 0 ? res + 360 : res;
  }

  var schoolSQL = function(opts, id) {
    var sql = 'WITH Q AS (' + opts.cartodb.sql + ') SELECT * FROM Q WHERE '
      + opts.properties.id + ' like \'' + id + '\'';

    return sql;
  }

  var schoolLoader = function(map,id){
    var sql = schoolSQL(map.opts, id);
    return ctx.sqlLoader(sql);
  }

  // Try to get the schools from the cache
  var lFeat = this.schools.es[distData.cod_es] ;
  var rFeat = this.schools.nz[distData.cod_nz] ;

  // If we got them, just assign them and move to the schools loading
  if (lFeat && rFeat){
    if (ctx.verbose){
      alertify.success("Rows " + distData.cod_es
      + " and " + distData.cod_nz + " loaded from cache");
    }
    this.leftMap.feat = lFeat;
    this.rightMap.feat = rFeat;
    this.loadSchoolsData(distData);
  } else {
    // Take the info from CartoDB
    var defLeft = schoolLoader(ctx.leftMap,distData.cod_es);
    var defRight = schoolLoader(ctx.rightMap,distData.cod_nz);

    $.when(defLeft,defRight).done(function(leftResp,rightResp){
      //debugger;
      if (ctx.verbose){
        alertify.success("Rows " + distData.cod_es
          + " and " + distData.cod_nz + " retrieved from CartoDB");
      }
      var lResult = leftResp[0];
      var rResult = rightResp[0];

      if (lResult && rResult){
        var lRow = lResult.rows[0];
        var rRow = rResult.rows[0];

        ctx.schools.es[distData.cod_es] = ctx.leftMap.feat = lRow;
        ctx.schools.nz[distData.cod_nz] = ctx.rightMap.feat = rRow;

        ctx.loadSchoolsData(distData);
      } else {
        msgError("Error receiving row data","",ctx.verbose);
      }

    });
  }
};

AntipodesMaps.prototype.loadSchoolsData = function(distData) {

  var geom = new Geom();

  function getXYPoint(feature){
    return ol.proj.transform(feature,'EPSG:4326','EPSG:3857');
  }

  // update school details
  var updateDetails = function(map,feature){
    var opts = map.opts;
    var props = opts.properties

    var geoPoint = [feature[props.lon],feature[props.lat]];
    var geoCenter = map.getViewGeoPoint();
    var xyPoint = getXYPoint(geoPoint);
    var xyCenter = map.getView().getCenter();

    // Set the selector or print the div
    var divDetails = $(opts.idprefix + '-details');
    divDetails.find('.schoolname')
      .text(feature[props.name]);

    divDetails.find(" .schooladdress")
      .text(feature[props.address] || '...');
    divDetails.find(" .lon")
      .text(geoPoint[0].toFixed(4));
    divDetails.find(" .lat")
      .text(geoPoint[1].toFixed(4));
    var dist = geom.distance(geoPoint,geoCenter,true);
    divDetails.find(" .disttocross")
      .text( dist.toFixed(1)  + " kms");
    var dir;
    if ( dist < .1 ) {
      dir = '';
    } else {
      dir = geom.direction(xyCenter,xyPoint).toFixed(4)+'º'
    }
    $(opts.idprefix + " .direction").text(dir);
  }

  var lFeat = this.leftMap.feat;
  var rFeat = this.rightMap.feat;
  var dist = distData.dist;
  var tunn = distData.tunn;

  if (lFeat && rFeat){
    // Get the geodesic points

    // features
    var lll = lFeat.lon;
    var rll = lFeat.lat;

    // views
    var clll = this.leftMap.getViewGeoPoint();
    var crll = this.rightMap.getViewGeoPoint();

    // Render the template
    $('#distance').html(
        '' +
        lFeat[this.opts.left.properties.name] + ' and ' +
        '' +
        rFeat[this.opts.right.properties.name] + ' are ' +
        '' +
        addCommas(dist.toFixed(1)) + ' kms away!! '+
        '(' +
        addCommas(tunn.toFixed(1)) + ' km as a tunnel)'
    );
    updateDetails(this.leftMap,lFeat);
    updateDetails(this.rightMap,rFeat);
  }
};
<commit_msg>fixes 31, had a wrong jquery selector<commit_after>'use strict';

/**
 * Class to coordinate work together
 */
function AntipodesMaps(opts) {
  this.opts = opts;
  this.verbose = opts.verbose != null || false;
  var ctx = this;

  // http://vehrka.cartodb.com/api/v2/viz/9fede618-6e3d-11e4-8fc1-0e853d047bba/viz.json

  $.ajax({
    url: 'http://'+ this.opts.cartodb.user + '.cartodb.com/api/v2/viz/' + this.opts.cartodb.viz + '/viz.json',
    contentType: 'text/plain',
    xhrFields: {
      withCredentials: false
    },
    dataType: "jsonp"
  }).then(function (response){
    if (ctx.verbose){
      alertify.success("Data visualization configuration loaded!");
    }
    // Configure map options with CartoDB Response
    var layers = response.layers[1].options.layer_definition.layers;
    var esData = layers.filter(function(l){
        return l.options.layer_name === opts.left.properties.layername;
      });
    var nzData = layers.filter(function(l){
        return l.options.layer_name === opts.right.properties.layername
      });

    if (esData.length == 1 && nzData.length == 1){
      opts.left.cartodb = esData[0].options;
      opts.right.cartodb = nzData[0].options;
    }

    ctx.setUpMaps(opts);
  });
}

AntipodesMaps.prototype.setUpMaps = function(opts) {
    this.leftMap =  new AntipodeMap(opts.center,opts.left,this);
    this.rightMap = this.leftMap.getAntipode(opts.right);
    this.schools = {
      "es":{},
      "nz":{}
    };

    this.setUpTriggers(this.leftMap);

    // Set up the central cross position
    var mapwidth = parseInt($('.map').css('width').replace('px',''));
    var crosswidth = parseInt($('.center-cross').css('width').replace('px',''));
    var leftCross = (mapwidth - crosswidth) / 2;

    $('.center-cross').css('left',leftCross + 'px');
};

AntipodesMaps.prototype.setUpTriggers = function(antipodeMap){
  var map = antipodeMap.map;
  var ctx = this;

  map.on('moveend',function(event){

    var now = new Date();
    var doIt = false;

    if (! ctx.lastDistSQL){
      ctx.lastDistSQL = now;
      doIt = true;
    } else if (ctx.lastDistSQL && (now - ctx.lastDistSQL) > 2000 ){
      doIt = true;
    }

    if (doIt){
      var center = ol.proj.transform(this.getView().getCenter(),'EPSG:3857','EPSG:4326');

      var distSQL = 'SELECT cod_es, cod_nz, dist, tunn FROM gvlc_getschools(st_geomfromtext(\'POINT('
        + center[0] + ' ' + center[1] + ')\'))';

      ctx.sqlLoader(distSQL).then(
        function(response){
          if (ctx.verbose){
            alertify.success("Distance between schools retreived");
          }
          var result = response.rows[0];
          ctx.updateDist(result);
        }, function(error){
          msgError("Error obtaining distance of schools",error,ctx.verbose);
        }
      );

      ctx.lastDistSQL = new Date();
    }

  });
}

AntipodesMaps.prototype.sqlLoader = function(sql) {
  return $.ajax({
    url: 'https://'+ this.opts.cartodb.user + '.cartodb.com/api/v2/sql?q=' + encodeURIComponent(sql),
    contentType: 'text/plain',
    xhrFields: {
      withCredentials: false
    },
    dataType: "jsonp"
  });
}

AntipodesMaps.prototype.updateDist = function(distData) {
  var ctx = this;

  function direction(from,to){
    var iY = to[1] - from[1];
    var iX = to[0] - from[0];
    var res = Math.atan2(iX,iY).toDeg();
    return res < 0 ? res + 360 : res;
  }

  var schoolSQL = function(opts, id) {
    var sql = 'WITH Q AS (' + opts.cartodb.sql + ') SELECT * FROM Q WHERE '
      + opts.properties.id + ' like \'' + id + '\'';

    return sql;
  }

  var schoolLoader = function(map,id){
    var sql = schoolSQL(map.opts, id);
    return ctx.sqlLoader(sql);
  }

  // Try to get the schools from the cache
  var lFeat = this.schools.es[distData.cod_es] ;
  var rFeat = this.schools.nz[distData.cod_nz] ;

  // If we got them, just assign them and move to the schools loading
  if (lFeat && rFeat){
    if (ctx.verbose){
      alertify.success("Rows " + distData.cod_es
      + " and " + distData.cod_nz + " loaded from cache");
    }
    this.leftMap.feat = lFeat;
    this.rightMap.feat = rFeat;
    this.loadSchoolsData(distData);
  } else {
    // Take the info from CartoDB
    var defLeft = schoolLoader(ctx.leftMap,distData.cod_es);
    var defRight = schoolLoader(ctx.rightMap,distData.cod_nz);

    $.when(defLeft,defRight).done(function(leftResp,rightResp){
      //debugger;
      if (ctx.verbose){
        alertify.success("Rows " + distData.cod_es
          + " and " + distData.cod_nz + " retrieved from CartoDB");
      }
      var lResult = leftResp[0];
      var rResult = rightResp[0];

      if (lResult && rResult){
        var lRow = lResult.rows[0];
        var rRow = rResult.rows[0];

        ctx.schools.es[distData.cod_es] = ctx.leftMap.feat = lRow;
        ctx.schools.nz[distData.cod_nz] = ctx.rightMap.feat = rRow;

        ctx.loadSchoolsData(distData);
      } else {
        msgError("Error receiving row data","",ctx.verbose);
      }

    });
  }
};

AntipodesMaps.prototype.loadSchoolsData = function(distData) {

  var geom = new Geom();

  function getXYPoint(feature){
    return ol.proj.transform(feature,'EPSG:4326','EPSG:3857');
  }

  // update school details
  var updateDetails = function(map,feature){
    var opts = map.opts;
    var props = opts.properties

    var geoPoint = [feature[props.lon],feature[props.lat]];
    var geoCenter = map.getViewGeoPoint();
    var xyPoint = getXYPoint(geoPoint);
    var xyCenter = map.getView().getCenter();

    // Set the selector or print the div
    var divDetails = $(opts.idprefix + '-details');
    divDetails.find('.schoolname')
      .text(feature[props.name]);

    divDetails.find(" .schooladdress")
      .text(feature[props.address] || '...');
    divDetails.find(" .lon")
      .text(geoPoint[0].toFixed(4));
    divDetails.find(" .lat")
      .text(geoPoint[1].toFixed(4));
    var dist = geom.distance(geoPoint,geoCenter,true);
    divDetails.find(" .disttocross")
      .text( dist.toFixed(1)  + " kms");
    var dir;
    if ( dist < .1 ) {
      dir = '';
    } else {
      dir = geom.direction(xyCenter,xyPoint).toFixed(4)+'º'
    }
    $(opts.idprefix + "-details .direction").text(dir);
  }

  var lFeat = this.leftMap.feat;
  var rFeat = this.rightMap.feat;
  var dist = distData.dist;
  var tunn = distData.tunn;

  if (lFeat && rFeat){
    // Get the geodesic points

    // features
    var lll = lFeat.lon;
    var rll = lFeat.lat;

    // views
    var clll = this.leftMap.getViewGeoPoint();
    var crll = this.rightMap.getViewGeoPoint();

    // Render the template
    $('#distance').html(
        '' +
        lFeat[this.opts.left.properties.name] + ' and ' +
        '' +
        rFeat[this.opts.right.properties.name] + ' are ' +
        '' +
        addCommas(dist.toFixed(1)) + ' kms away!! '+
        '(' +
        addCommas(tunn.toFixed(1)) + ' km as a tunnel)'
    );
    updateDetails(this.leftMap,lFeat);
    updateDetails(this.rightMap,rFeat);
  }
};
<|endoftext|>


<commit_before>function wrap_edition(edition) {
  return edition;
} // wrap_edition

module.exports = wrap_edition;

////////////////////////////////////////////////
<commit_msg>default business_proposition to false<commit_after>function wrap_edition(edition) {
  switch (edition._type) {
  case 'ArticleEdition':
    return new ArticleEdition(edition);
  case 'CaseStudyEdition':
    return new CaseStudyEdition(edition);
  case 'CourseEdition':
    return new CourseEdition(edition);
  case 'CourseInstanceEdition':
    return new CourseInstanceEdition(edition);
  case 'EventEdition':
    return new EventEdition(edition);
  case 'JobEdition':
    return new JobEdition(edition);
  case 'NodeEdition':
    return new NodeEdition(edition);
  case 'OrganizationEdition':
    return new OrganizationEdition(edition);
  case 'PersonEdition':
    return new PersonEdition(edition);
  case 'ReportEdition':
    return new ReportEdition(edition);
  case 'TimedItemEdition':
    return new TimedItemEdition(edition);
  default:
    if (edition._type)
      console.log(`No wrapper class for ${edition._type}`);
    return new Edition(edition);
  } // switch ...
} // wrap_edition

module.exports = wrap_edition;

////////////////////////////////////////////////
class Edition {
  constructor(edition) {
    this.business_propostion = false;

    for (const [k,v] of Object.entries(edition))
      this[k] = v;
  } // constructor

  get rendering_path() { return `/${this.slug}`; }
} // class Edition

class ArticleEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.content; }

  get rendering_path() {
    console.log("ArticleEdition work to do in rendering_path?");
    return `/${this.slug}`;
  }
} // ArticleEdition

class CaseStudyEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.content; }

  get rendering_path() { return `/case-studies/${this.slug}`; }
} // CaseStudyEdition

class CourseEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.description; }

  get rendering_path() { return `/courses/${this.slug}`; }
} // class CourseEdition

class CourseInstanceEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.description; }

  get rendering_path() {
    console.log("CourseInstanceEdition - verify rendering_path");
    return `/courses/${this.course}/${this.date}`;
  }
} // class CourseInstanceEdition

class CreativeWorkEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.description; }

  get rendering_path() { return `/culture/${this.slug}`; }
} // CreativeWorkEdition

class EventEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.description; }

  get rendering_path() {
    console.log("EventEdition work to do in rendering_path?");
    return `/${this.slug}`;
  }
} // EventEdition

class JobEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.description; }

  get rendering_path() { return `/jobs/${slug}`; }
} // class JobEdition

class NodeEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.description; }

  get rendering_path() { return `/nodes/${slug}`; }

  get latlng() { return [location[0], location[1]].join(','); }
} // class NodeEdition

class OrganizationEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.description; }

  get rendering_path() {
    console.log("OrganizationEdition work to do in rendering_path?");
    return `/${this.slug}`;
  }
} // class OrganizationEdition

class PersonEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.description; }

  get rendering_path() {
    console.log("PersonEdition work to do in rendering_path?");
    return `/${this.slug}`;
  }
} // class PersonEdition

class ReportEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return ""; }

  get rendering_path() { return `/reports/${this.slug}`; }
} // class ReportEdition

class TimedItemEdition extends Edition {
  constructor(edition) {
    super(edition);
  } // constructor

  get whole_body() { return this.content; }

  get rendering_path() {
    console.log("TimedItemEdition work to do in rendering_path?");
    return `/${this.slug}`;
  }
} // class TimedItemEdition

/*
def tag_to_rendering_path(url_map)
    section = artefact.tags.map{|x| url_map[x.tag_id]}.compact.uniq.join
    section = url_map[:default] if section.blank? && url_map[:default]
    "#{'/' unless section.blank?}#{section}/#{slug}"
end
*/
<|endoftext|>


<commit_before>"use strict";

const DiscordieDispatcher = require("./core/DiscordieDispatcher");

const events = require("events");
const request = require("./core/ApiRequest");
const DiscordieError = require("./core/DiscordieError");
const Constants = require("./Constants");
const Events = Constants.Events;
const GatewaySocket = require("./networking/ws/GatewaySocket");
const Utils = require("./core/Utils");

const GuildCollection = require("./collections/GuildCollection");
const ChannelCollection = require("./collections/ChannelCollection");
const UserCollection = require("./collections/UserCollection");
const GuildMemberCollection = require("./collections/GuildMemberCollection");
const MessageCollection = require("./collections/MessageCollection");
const PresenceCollection = require("./collections/PresenceCollection");
const VoiceStateCollection = require("./collections/VoiceStateCollection");
const VoiceConnectionCollection = require("./collections/VoiceConnectionCollection");
const User = require("./models/User");
const AuthenticatedUser = require("./models/AuthenticatedUser");

const IGuildCollection = require("./interfaces/IGuildCollection");
const IChannelCollection = require("./interfaces/IChannelCollection");
const IAuthenticatedUser = require("./interfaces/IAuthenticatedUser");
const IUserCollection = require("./interfaces/IUserCollection");
const IMessageCollection = require("./interfaces/IMessageCollection");
const IDirectMessageChannelCollection = require("./interfaces/IDirectMessageChannelCollection");
const IInviteManager = require("./interfaces/IInviteManager");

const MessageHandlerCache = require("./core/MessageHandlerCache");
const messageHandlerCache = new WeakMap();

const rest = require("./networking/rest");

const defaultOptions = {
  // todo: game name support
  //gameNameSupport: true,
  compressMessages: true,
};

function handleAuthLoginError(e) {
  this.pendingLogin = false;

  this.Dispatcher.emit(
    Events.DISCONNECTED,
    {error: new DiscordieError("Login failed", e.error)}
  );
}
function handleAuthLoginSuccess(e) {
  this.pendingLogin = false;
  this.token = e.token;
  delete e.token;
  delete e.password;

  rest(this).gateway();
}

function handleGatewayError(e) {
  this.pendingLogin = false;

  this.Dispatcher.emit(
    Events.DISCONNECTED,
    {error: new DiscordieError("Could not get gateway", e.error)}
  );
}
function handleGatewaySuccess(e) {
  this.pendingLogin = false;

  this.gatewayEndpoint = e.gateway;
  this._createPrimaryGateway();
}

function registerVoiceEvents() {
  this.Dispatcher.on(Events.VOICE_SESSION_DESCRIPTION, e => {
    this.voiceConnections.push(e.socket);
  });
  this.Dispatcher.on(Events.VOICESOCKET_DISCONNECT, e => {
    this.voiceConnections =
      this.voiceConnections.filter((s) => s != e.socket);
  });
}

function registerGatewayHandlers() {
  this.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
    const handlers = messageHandlerCache.get(this);
    if (!handlers.processGatewayMessage(e.socket, e.type, e.data) && !e.handled) {
      if (!e.socket.isPrimary) return;
      return this.Dispatcher.emit(
        Events.GATEWAY_UNHANDLED_MESSAGE,
        {type: e.type, data: e.data}
      );
    }
    if (e.handled) delete e.handled;
  });

  const onVoiceMessage = (type, e) => {
    const handlers = messageHandlerCache.get(this);
    if (!handlers.processVoiceMessage(e.socket, type, e.data) && !e.handled) {
      return this.Dispatcher.emit(
        Events.VOICESOCKET_UNHANDLED_MESSAGE,
        {type: type, data: e.data}
      );
    }
    if (e.handled) delete e.handled;
  };

  this.Dispatcher.on(Events.VOICE_READY, e => {
    onVoiceMessage("READY", e);
  });
  this.Dispatcher.on(Events.VOICE_SESSION_DESCRIPTION, e => {
    onVoiceMessage("SESSION_DESCRIPTION", e);
  });
  this.Dispatcher.on(Events.VOICE_SPEAKING, e => {
    onVoiceMessage("SPEAKING", e);
  });
}

/**
 * @class
 */
class Discordie {
  constructor(options) {
    messageHandlerCache.set(this, new MessageHandlerCache(this));

    if (!options) options = defaultOptions;
    this.options = options;
    Object.defineProperty(this, "options", {writable: false});

    this.Dispatcher = new DiscordieDispatcher();

    // todo: handle cleanup when voice connection drops
    this.voiceConnections = []; // todo: remove this.voiceConnections
    this.gatewaySocket = null;

    this.Dispatcher.on(Events.DISCONNECTED, (e) => {
      this.VoiceConnections.disconnectSecondary();
    });

    const gw = () => this.gatewaySocket;

    this._user = new AuthenticatedUser();
    this._guilds = new GuildCollection(this, gw);
    this._channels = new ChannelCollection(this, gw);
    this._users = new UserCollection(this, gw);
    this._members = new GuildMemberCollection(this, gw);
    this._presences = new PresenceCollection(this, gw);
    this._messages = new MessageCollection(this, gw);
    this._voicestates = new VoiceStateCollection(this, gw);

    // == PUBLIC == //

    /**
     * An instance of IAuthenticatedUser.
     * @returns {IAuthenticatedUser}
     */
    this.User = new IAuthenticatedUser(this);

    /**
     * An instance of IGuildCollection.
     * @returns {IGuildCollection}
     */
    this.Guilds = new IGuildCollection(this,
      () => this._guilds.values());

    /**
     * An instance of IChannelCollection.
     * @returns {IChannelCollection}
     */
    this.Channels = new IChannelCollection(this,
      () => this._channels.getGuildChannelIterator());

    /**
     * An instance of IUserCollection.
     * @returns {IUserCollection}
     */
    this.Users = new IUserCollection(this,
      () => this._users.values());

    /**
     * An instance of IDirectMessageChannelCollection.
     * @returns {IDirectMessageChannelCollection}
     */
    this.DirectMessageChannels = new IDirectMessageChannelCollection(this,
      () => this._channels.getPrivateChannelIterator());

    /**
     * An instance of IMessageCollection.
     * @returns {IMessageCollection}
     */
    this.Messages = new IMessageCollection(this,
      () => this._messages.getIterator());

    /**
     * An instance of IInviteManager.
     * @returns {IInviteManager}
     */
    this.Invites = new IInviteManager(this);

    /**
     * An array of IVoiceConnection.
     * @returns {Array<IVoiceConnection>}
     */
    this.VoiceConnections =
      new VoiceConnectionCollection(this, () => this.gatewaySocket);

    // == EVENTS == //

    this.Dispatcher.on(Events.REQUEST_AUTH_LOGIN_ERROR, handleAuthLoginError.bind(this));
    this.Dispatcher.on(Events.REQUEST_AUTH_LOGIN_SUCCESS, handleAuthLoginSuccess.bind(this));

    this.Dispatcher.on(Events.REQUEST_GATEWAY_ERROR, handleGatewayError.bind(this));
    this.Dispatcher.on(Events.REQUEST_GATEWAY_SUCCESS, handleGatewaySuccess.bind(this));

    // must register our gateway/voice events last to check e.handled

    registerGatewayHandlers.call(this);
    registerVoiceEvents.call(this);

    Utils.privatify(this);
  }

  /**
   * Current state.
   * @returns {String}
   */
  get state() {
    if (this.pendingLogin)
      return Constants.DiscordieState.LOGGING_IN;

    if (this.gatewaySocket) {
      if (this.gatewaySocket.connected)
        return Constants.DiscordieState.CONNECTED;
      if (this.gatewaySocket.connecting)
        return Constants.DiscordieState.CONNECTING;
    }

    if (this.token)
      return Constants.DiscordieState.LOGGED_IN;

    return Constants.DiscordieState.DISCONNECTED;
  }

  /**
   * Gets a value indicating whether the websocket connection is established.
   * @returns {boolean}
   */
  get connected() {
    return this.state == Constants.DiscordieState.CONNECTED;
  }

  /**
   * @param {Object} credentials - Can contain `email`, `password` or `token`
   * @param {Boolean} forceNewSession - Forces to log in with email and password
   */
  connect(credentials, forceNewSession) {
    if (this.state == Constants.DiscordieState.CONNECTED
      || this.state == Constants.DiscordieState.CONNECTING
      || this.pendingLogin)
      return;

    if (forceNewSession) {
      this.disconnect();
      this.token = null;
    }

    this.pendingLogin = true;

    if (credentials && credentials.token) {
      this.token = credentials.token;
      credentials = null;
    }

    if (!credentials && this.token) {
      rest(this).gateway();
      return;
    }

    rest(this).auth.login(credentials);
  }

  /**
   * Disconnects primary websocket.
   */
  disconnect() {
    this.VoiceConnections.disconnectSecondary();
    if (this.gatewaySocket) {
      this.gatewaySocket.disconnect();
      this.gatewaySocket = null;
    }
  }

  _createPrimaryGateway() {
    if (!this.gatewaySocket)
      this.gatewaySocket = new GatewaySocket(this, this.options.compressMessages);
    this.gatewaySocket.connect(this.gatewayEndpoint);
  }
  _createSecondaryGateway() {
    const gw = new GatewaySocket(this, this.options.compressMessages);
    gw.connect(this.gatewayEndpoint);
    return gw;
  }
}

Discordie.Events = Constants.Events;
Discordie.StatusTypes = Constants.StatusTypes;
Discordie.States = Constants.DiscordieState;

module.exports = Discordie;
<commit_msg>Remove deprecated .voiceConnections<commit_after>"use strict";

const DiscordieDispatcher = require("./core/DiscordieDispatcher");

const events = require("events");
const request = require("./core/ApiRequest");
const DiscordieError = require("./core/DiscordieError");
const Constants = require("./Constants");
const Events = Constants.Events;
const GatewaySocket = require("./networking/ws/GatewaySocket");
const Utils = require("./core/Utils");

const GuildCollection = require("./collections/GuildCollection");
const ChannelCollection = require("./collections/ChannelCollection");
const UserCollection = require("./collections/UserCollection");
const GuildMemberCollection = require("./collections/GuildMemberCollection");
const MessageCollection = require("./collections/MessageCollection");
const PresenceCollection = require("./collections/PresenceCollection");
const VoiceStateCollection = require("./collections/VoiceStateCollection");
const VoiceConnectionCollection = require("./collections/VoiceConnectionCollection");
const User = require("./models/User");
const AuthenticatedUser = require("./models/AuthenticatedUser");

const IGuildCollection = require("./interfaces/IGuildCollection");
const IChannelCollection = require("./interfaces/IChannelCollection");
const IAuthenticatedUser = require("./interfaces/IAuthenticatedUser");
const IUserCollection = require("./interfaces/IUserCollection");
const IMessageCollection = require("./interfaces/IMessageCollection");
const IDirectMessageChannelCollection = require("./interfaces/IDirectMessageChannelCollection");
const IInviteManager = require("./interfaces/IInviteManager");

const MessageHandlerCache = require("./core/MessageHandlerCache");
const messageHandlerCache = new WeakMap();

const rest = require("./networking/rest");

const defaultOptions = {
  // todo: game name support
  //gameNameSupport: true,
  compressMessages: true,
};

function handleAuthLoginError(e) {
  this.pendingLogin = false;

  this.Dispatcher.emit(
    Events.DISCONNECTED,
    {error: new DiscordieError("Login failed", e.error)}
  );
}
function handleAuthLoginSuccess(e) {
  this.pendingLogin = false;
  this.token = e.token;
  delete e.token;
  delete e.password;

  rest(this).gateway();
}

function handleGatewayError(e) {
  this.pendingLogin = false;

  this.Dispatcher.emit(
    Events.DISCONNECTED,
    {error: new DiscordieError("Could not get gateway", e.error)}
  );
}
function handleGatewaySuccess(e) {
  this.pendingLogin = false;

  this.gatewayEndpoint = e.gateway;
  this._createPrimaryGateway();
}

function registerGatewayHandlers() {
  this.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
    const handlers = messageHandlerCache.get(this);
    if (!handlers.processGatewayMessage(e.socket, e.type, e.data) && !e.handled) {
      if (!e.socket.isPrimary) return;
      return this.Dispatcher.emit(
        Events.GATEWAY_UNHANDLED_MESSAGE,
        {type: e.type, data: e.data}
      );
    }
    if (e.handled) delete e.handled;
  });

  const onVoiceMessage = (type, e) => {
    const handlers = messageHandlerCache.get(this);
    if (!handlers.processVoiceMessage(e.socket, type, e.data) && !e.handled) {
      return this.Dispatcher.emit(
        Events.VOICESOCKET_UNHANDLED_MESSAGE,
        {type: type, data: e.data}
      );
    }
    if (e.handled) delete e.handled;
  };

  this.Dispatcher.on(Events.VOICE_READY, e => {
    onVoiceMessage("READY", e);
  });
  this.Dispatcher.on(Events.VOICE_SESSION_DESCRIPTION, e => {
    onVoiceMessage("SESSION_DESCRIPTION", e);
  });
  this.Dispatcher.on(Events.VOICE_SPEAKING, e => {
    onVoiceMessage("SPEAKING", e);
  });
}

/**
 * @class
 */
class Discordie {
  constructor(options) {
    messageHandlerCache.set(this, new MessageHandlerCache(this));

    if (!options) options = defaultOptions;
    this.options = options;
    Object.defineProperty(this, "options", {writable: false});

    this.Dispatcher = new DiscordieDispatcher();

    this.gatewaySocket = null;

    this.Dispatcher.on(Events.DISCONNECTED, (e) => {
      this.VoiceConnections.disconnectSecondary();
    });

    const gw = () => this.gatewaySocket;

    this._user = new AuthenticatedUser();
    this._guilds = new GuildCollection(this, gw);
    this._channels = new ChannelCollection(this, gw);
    this._users = new UserCollection(this, gw);
    this._members = new GuildMemberCollection(this, gw);
    this._presences = new PresenceCollection(this, gw);
    this._messages = new MessageCollection(this, gw);
    this._voicestates = new VoiceStateCollection(this, gw);

    // == PUBLIC == //

    /**
     * An instance of IAuthenticatedUser.
     * @returns {IAuthenticatedUser}
     */
    this.User = new IAuthenticatedUser(this);

    /**
     * An instance of IGuildCollection.
     * @returns {IGuildCollection}
     */
    this.Guilds = new IGuildCollection(this,
      () => this._guilds.values());

    /**
     * An instance of IChannelCollection.
     * @returns {IChannelCollection}
     */
    this.Channels = new IChannelCollection(this,
      () => this._channels.getGuildChannelIterator());

    /**
     * An instance of IUserCollection.
     * @returns {IUserCollection}
     */
    this.Users = new IUserCollection(this,
      () => this._users.values());

    /**
     * An instance of IDirectMessageChannelCollection.
     * @returns {IDirectMessageChannelCollection}
     */
    this.DirectMessageChannels = new IDirectMessageChannelCollection(this,
      () => this._channels.getPrivateChannelIterator());

    /**
     * An instance of IMessageCollection.
     * @returns {IMessageCollection}
     */
    this.Messages = new IMessageCollection(this,
      () => this._messages.getIterator());

    /**
     * An instance of IInviteManager.
     * @returns {IInviteManager}
     */
    this.Invites = new IInviteManager(this);

    /**
     * An array of IVoiceConnection.
     * @returns {Array<IVoiceConnection>}
     */
    this.VoiceConnections =
      new VoiceConnectionCollection(this, () => this.gatewaySocket);

    // == EVENTS == //

    this.Dispatcher.on(Events.REQUEST_AUTH_LOGIN_ERROR, handleAuthLoginError.bind(this));
    this.Dispatcher.on(Events.REQUEST_AUTH_LOGIN_SUCCESS, handleAuthLoginSuccess.bind(this));

    this.Dispatcher.on(Events.REQUEST_GATEWAY_ERROR, handleGatewayError.bind(this));
    this.Dispatcher.on(Events.REQUEST_GATEWAY_SUCCESS, handleGatewaySuccess.bind(this));

    // must register our gateway/voice events last to check e.handled

    registerGatewayHandlers.call(this);

    Utils.privatify(this);
  }

  /**
   * Current state.
   * @returns {String}
   */
  get state() {
    if (this.pendingLogin)
      return Constants.DiscordieState.LOGGING_IN;

    if (this.gatewaySocket) {
      if (this.gatewaySocket.connected)
        return Constants.DiscordieState.CONNECTED;
      if (this.gatewaySocket.connecting)
        return Constants.DiscordieState.CONNECTING;
    }

    if (this.token)
      return Constants.DiscordieState.LOGGED_IN;

    return Constants.DiscordieState.DISCONNECTED;
  }

  /**
   * Gets a value indicating whether the websocket connection is established.
   * @returns {boolean}
   */
  get connected() {
    return this.state == Constants.DiscordieState.CONNECTED;
  }

  /**
   * @param {Object} credentials - Can contain `email`, `password` or `token`
   * @param {Boolean} forceNewSession - Forces to log in with email and password
   */
  connect(credentials, forceNewSession) {
    if (this.state == Constants.DiscordieState.CONNECTED
      || this.state == Constants.DiscordieState.CONNECTING
      || this.pendingLogin)
      return;

    if (forceNewSession) {
      this.disconnect();
      this.token = null;
    }

    this.pendingLogin = true;

    if (credentials && credentials.token) {
      this.token = credentials.token;
      credentials = null;
    }

    if (!credentials && this.token) {
      rest(this).gateway();
      return;
    }

    rest(this).auth.login(credentials);
  }

  /**
   * Disconnects primary websocket.
   */
  disconnect() {
    this.VoiceConnections.disconnectSecondary();
    if (this.gatewaySocket) {
      this.gatewaySocket.disconnect();
      this.gatewaySocket = null;
    }
  }

  _createPrimaryGateway() {
    if (!this.gatewaySocket)
      this.gatewaySocket = new GatewaySocket(this, this.options.compressMessages);
    this.gatewaySocket.connect(this.gatewayEndpoint);
  }
  _createSecondaryGateway() {
    const gw = new GatewaySocket(this, this.options.compressMessages);
    gw.connect(this.gatewayEndpoint);
    return gw;
  }
}

Discordie.Events = Constants.Events;
Discordie.StatusTypes = Constants.StatusTypes;
Discordie.States = Constants.DiscordieState;

module.exports = Discordie;
<|endoftext|>


<commit_before>var Ul = require("ul");
var Typpy = require("typpy");
var Deffy = require("deffy");
var IterateObject = require("iterate-object");
var SetOrGet = require("set-or-get");
var ObjectMap = require("map-o");

const TYPES = (function () {

    function types(a, b) {
        if (!a || !b) { return false; }
        if (typeof a === "string") {
            a = { type: a };
        }
        if (typeof b === "string") {
            b = { type: b };
        }
        return a.type === b.type;
    }

    // :some/datahandler
    types.dataHandler = {
        icon: "f087"
    };

    // !some/error-handler
    types.errorHandler = {
        icon: "f02d"
    };

    // instance/method
    types.streamHandler = {
        icon: "f0c4"
    };

    // ["load", ["foo"]]
    types.load = {
        handler: "LOAD"
    };

    // ["instance/emit", "some-event"]
    types.emit = {
        icon: "f077"
    };

    // ["link", "instance/method"]
    types.link = {
        icon: "f05c",
        handler: "flow"
    };

    // "event"
    types.listener = {
        icon: "f030"
    };

    ObjectMap(types, function (name, value) {
        if (value.icon) {
            value.icon = "&#x" + value.icon;
        }
        value.type = name;
        value.name = name;
        return value;
    });

    return types;
})();

function Enny() {
    var self = this;
    self.instances = {};
    self.Instance = function (data) {
        return new Enny.Instance(data, {
            enny: self
        });
    };
    self.FlowComponent = function (data) {
        return new Enny.FlowComponent(data, {
            enny: self
        });
    };
}

Enny.prototype.toObject = function () {
    return JSON.parse(JSON.stringify(this));
};

Enny.prototype.toJSON = function () {
    var self = this;
    var obj = {};
    Object.keys(self.instances).forEach(function (name) {
        obj[name] = self.instances[name]._;
    });
    return obj;
};

Enny.prototype.addInstance = function (ins) {
    ins = this.Instance(ins);
    this.instances[ins._.name] = ins;
    return ins;
};

Enny.Instance = function Instance (data, options) {
    if (Typpy(data) === "instance") {
        return data;
    }
    this._ = Ul.clone(data);
    this.enny = options.enny;
};

Enny.Instance.prototype.connect = function (ins, options, callback) {

    var self = this;
    if (typeof options === "boolean") {
        options = {
            client: options
        };
    } else if (options === "function") {
        callback = options;
        options = {};
    }

    callback = callback || function (err) {
        if (err) { console.error(err); }
    };
    options = Ul.merge(options, {
        client: true
    });
    ins = Enny.Instance(ins, options);

    if (!ins._.name) {
        return callback(new Error("The target instance name is required."));
    }

    if (!self._.name) {
        return callback(new Error("The source instance name is required."));
    }

    var load = null;
    if (options.client) {
        self._.client = Deffy(self._.client, {});
        load = self._.client.load = Deffy(self._.client.load, []);
    } else {
        load = self._.load = Deffy(self._.load, []);
    }
    load.push(ins._.name);
    if (options.save) {
        self.enny.save(callback);
        return self;
    }
    callback();
    return self;
};

Enny.Instance.prototype.addFlow = function (flElm, options, callback) {

    var self = this;
    if (typeof options === "boolean") {
        options = {
            client: options
        };
    } else if (options === "function") {
        callback = options;
        options = {};
    }

    callback = callback || function (err) {
        if (err) { console.error(err); }
    };

    options = Ul.merge(options, {
        client: true
    });

    var flow = null;
    if (options.client) {
        self._.client = Deffy(self._.client, {});
        flow = self._.client.flow = Deffy(self._.client.flow, []);
    } else {
        flow = self._.flow = Deffy(self._.flow, []);
    }

    flElm = new Enny.FlowElement(flElm);

    flow.push(flElm);

    if (options.save) {
        self.enny.save(callback);
        return self;
    }

    callback();
};

Enny.Instance.prototype.toObject = function () {
    return JSON.parse(JSON.stringify(this))._;
};

Enny.FlowElement = function FlowElement (data) {
    var self = this;
    if (Typpy(data) === "flowelement") {
        return data;
    }
    this._ = [];
    if (Typpy(data) === "array") {
        data.forEach(self.addComponent.bind(self));
    }
};

Enny.FlowElement.prototype.toJSON = function () {
    return this._.map(function (c) {
        return c.toFlow();
    });
};

Enny.FlowElement.prototype.addComponent = function (data) {
    data = new Enny.FlowComponent(data);
    this._.push(data);
};

Enny.FlowElement.prototype.toFlow = function () {
    return this._.map(function (c) {
        return c.toFlow();
    });
};

Enny.Handler = function Handler(data) {
    if (Typpy(data) === "handler") {
        return data;
    }
    this.to = data.to;
    this.args = Deffy(data.args, []);
    this.isStream = Deffy(data.isStream, true);
    this.handler = data.handler;
};

Enny.Handler.prototype.toFlow = function () {
    var res = [];
    res[0] = (this.isStream ? "" : ":") + (this.to ? this.to + "/" : "") + this.handler;
    if (!this.args.length) {
        return res[0];
    }
    res = res.concat(this.args);
    return res;
};

Enny.FlowComponent = function FlowComponent (data) {
    var self = this;
    if (Typpy(data) === "flowcomponent") {
        return data;
    }
    if (data.event) {
        data.type = TYPES.listener;
    }
    if (data.stream) {
        data.type = TYPES.streamHandler;
        data.handler = data.stream;
    }
    if (data.link) {
        data.type = TYPES.link;
    }
    self.data = Ul.clone(data);
};

Enny.FlowComponent.prototype.toFlow = function () {
    var data = this.data;
    var res = null;
    switch (data.type) {
        case TYPES.listener.type:
            if (data.once) {
                return [data.event];
            }
            return data.event;
        case TYPES.link.type:
            return new Enny.Handler({
                args: [data.link],
                handler: TYPES.link.handler
            }).toFlow();
        case TYPES.dataHandler.type:
        case TYPES.streamHandler.type:
            return new Enny.Handler({
                to: data.to,
                isStream: TYPES(data.type, TYPES.streamHandler),
                args: data.args,
                handler: data.handler
            }).toFlow();
        case TYPES.load.type:
            return new Enny.Handler({
                args: [[data.instance]],
                handler: TYPES.load.handler
            }).toFlow();
    }
};

// instance/method
// !instance/method
// >instance/method
// :instance/method
// method
Enny.parseMethod = function (input, defaultIns) {
    var output = {
        instance: defaultIns,
        type: TYPES.streamHandler
    };
    switch (input.charAt(0)) {
        case "!":
            output.type = TYPES.errorHandler;
            input = input.substr(1);
            break;
        case ":":
            output.type = TYPES.dataHandler;
            input = input.substr(1);
            break;
        case ">":
            output.disableInput = true;
            output.type = TYPES.streamHandler;
            input = input.substr(1);
            break;
        case "@":
            output.type = TYPES.link;
            input = input.substr(1);
            break;
        default:
            break;
    }

    var splits = input.split("/");
    if (splits.length === 2) {
        output.instance = splits[0];
        output.method = splits[1];
    } else {
        output.method = splits[0];
    }
    return output;
}

Enny.parseFlowComponent = function (_input, instName) {
    var input = Ul.clone(_input);

    if (Typpy(input, String)) {
        input = [input];
    }

    var output = {}
      , eP = null
      , mP = null
      ;

    // Load
    if (input[0] === TYPES.load.handler) {
        output.type = TYPES.load;
        output.args = input.slice(1);
    // Emit/link
    } else if ((eP = Enny.parseMethod(input[0], instName)).method === "flow") {
        if (TYPES((mP = Enny.parseMethod(input[1], instName)).type, TYPES.link)) {
            output.type = TYPES.link;
            output.instance = mP.instance;
            output.serverMethod = mP.method;
        } else {
            output.type = TYPES.emit;
            output.instance = eP.instance;
            output.event = input[1];
        }
    }

    // Stream handler
    if (!output.type) {
        output = Enny.parseMethod(input[0], instName);
        output.args = input.slice(1);
    }

    return output;
};

Enny.instanceFlow = function (_input, name) {
    var output = {
        load: {},
        dataHandler: {},
        errorHandler: {},
        streamHandler: {},
        emit: {},
        listener: {}
    };

    if (!_input.length) {
        return output;
    }

    IterateObject(_input, function (f) {
        // Collect listeners
        output.listener[f[0]] = {
            event: f[0],
            type: TYPES.listener
        };
        IterateObject(f.slice(1), function (c) {
            c = Enny.parseFlowComponent(c, name);
            if (c.instance !== name) { return; }
            output[c.type][c.method] = c;
        });
    });
    return output;
};

Enny.parseFlow = function (_input, instName) {

    var out = {};

    IterateObject(_input, function (elm) {
        var ev = SetOrGet(out, elm[0], []);
        var p = [];
        IterateObject(elm.slice(1), function (comp) {
            p.push(Enny.parseFlowComponent(comp, instName));
        });
        ev.push(p);
    });

    return out;
};

Enny.convertToOn = function (input) {
    if (input.serverMethod || TYPES(input.type, TYPES.emit)) {
        return TYPES.listener;
    }
    return input.type;
};

Enny.TYPES = TYPES;

module.exports = Enny;
<commit_msg>Add all parsed fields<commit_after>var Ul = require("ul");
var Typpy = require("typpy");
var Deffy = require("deffy");
var IterateObject = require("iterate-object");
var SetOrGet = require("set-or-get");
var ObjectMap = require("map-o");

const TYPES = (function () {

    function types(a, b) {
        if (!a || !b) { return false; }
        if (typeof a === "string") {
            a = { type: a };
        }
        if (typeof b === "string") {
            b = { type: b };
        }
        return a.type === b.type;
    }

    // :some/datahandler
    types.dataHandler = {
        icon: "f087"
    };

    // !some/error-handler
    types.errorHandler = {
        icon: "f02d"
    };

    // instance/method
    types.streamHandler = {
        icon: "f0c4"
    };

    // ["load", ["foo"]]
    types.load = {
        handler: "LOAD"
    };

    // ["instance/emit", "some-event"]
    types.emit = {
        icon: "f077"
    };

    // ["link", "instance/method"]
    types.link = {
        icon: "f05c",
        handler: "flow"
    };

    // "event"
    types.listener = {
        icon: "f030"
    };

    ObjectMap(types, function (name, value) {
        if (value.icon) {
            value.icon = "&#x" + value.icon;
        }
        value.type = name;
        value.name = name;
        return value;
    });

    return types;
})();

function Enny() {
    var self = this;
    self.instances = {};
    self.Instance = function (data) {
        return new Enny.Instance(data, {
            enny: self
        });
    };
    self.FlowComponent = function (data) {
        return new Enny.FlowComponent(data, {
            enny: self
        });
    };
}

Enny.prototype.toObject = function () {
    return JSON.parse(JSON.stringify(this));
};

Enny.prototype.toJSON = function () {
    var self = this;
    var obj = {};
    Object.keys(self.instances).forEach(function (name) {
        obj[name] = self.instances[name]._;
    });
    return obj;
};

Enny.prototype.addInstance = function (ins) {
    ins = this.Instance(ins);
    this.instances[ins._.name] = ins;
    return ins;
};

Enny.Instance = function Instance (data, options) {
    if (Typpy(data) === "instance") {
        return data;
    }
    this._ = Ul.clone(data);
    this.enny = options.enny;
};

Enny.Instance.prototype.connect = function (ins, options, callback) {

    var self = this;
    if (typeof options === "boolean") {
        options = {
            client: options
        };
    } else if (options === "function") {
        callback = options;
        options = {};
    }

    callback = callback || function (err) {
        if (err) { console.error(err); }
    };
    options = Ul.merge(options, {
        client: true
    });
    ins = Enny.Instance(ins, options);

    if (!ins._.name) {
        return callback(new Error("The target instance name is required."));
    }

    if (!self._.name) {
        return callback(new Error("The source instance name is required."));
    }

    var load = null;
    if (options.client) {
        self._.client = Deffy(self._.client, {});
        load = self._.client.load = Deffy(self._.client.load, []);
    } else {
        load = self._.load = Deffy(self._.load, []);
    }
    load.push(ins._.name);
    if (options.save) {
        self.enny.save(callback);
        return self;
    }
    callback();
    return self;
};

Enny.Instance.prototype.addFlow = function (flElm, options, callback) {

    var self = this;
    if (typeof options === "boolean") {
        options = {
            client: options
        };
    } else if (options === "function") {
        callback = options;
        options = {};
    }

    callback = callback || function (err) {
        if (err) { console.error(err); }
    };

    options = Ul.merge(options, {
        client: true
    });

    var flow = null;
    if (options.client) {
        self._.client = Deffy(self._.client, {});
        flow = self._.client.flow = Deffy(self._.client.flow, []);
    } else {
        flow = self._.flow = Deffy(self._.flow, []);
    }

    flElm = new Enny.FlowElement(flElm);

    flow.push(flElm);

    if (options.save) {
        self.enny.save(callback);
        return self;
    }

    callback();
};

Enny.Instance.prototype.toObject = function () {
    return JSON.parse(JSON.stringify(this))._;
};

Enny.FlowElement = function FlowElement (data) {
    var self = this;
    if (Typpy(data) === "flowelement") {
        return data;
    }
    this._ = [];
    if (Typpy(data) === "array") {
        data.forEach(self.addComponent.bind(self));
    }
};

Enny.FlowElement.prototype.toJSON = function () {
    return this._.map(function (c) {
        return c.toFlow();
    });
};

Enny.FlowElement.prototype.addComponent = function (data) {
    data = new Enny.FlowComponent(data);
    this._.push(data);
};

Enny.FlowElement.prototype.toFlow = function () {
    return this._.map(function (c) {
        return c.toFlow();
    });
};

Enny.Handler = function Handler(data) {
    if (Typpy(data) === "handler") {
        return data;
    }
    this.to = data.to;
    this.args = Deffy(data.args, []);
    this.isStream = Deffy(data.isStream, true);
    this.handler = data.handler;
};

Enny.Handler.prototype.toFlow = function () {
    var res = [];
    res[0] = (this.isStream ? "" : ":") + (this.to ? this.to + "/" : "") + this.handler;
    if (!this.args.length) {
        return res[0];
    }
    res = res.concat(this.args);
    return res;
};

Enny.FlowComponent = function FlowComponent (data) {
    var self = this;
    if (Typpy(data) === "flowcomponent") {
        return data;
    }
    if (data.event) {
        data.type = TYPES.listener;
    }
    if (data.stream) {
        data.type = TYPES.streamHandler;
        data.handler = data.stream;
    }
    if (data.link) {
        data.type = TYPES.link;
    }
    self.data = Ul.clone(data);
};

Enny.FlowComponent.prototype.toFlow = function () {
    var data = this.data;
    var res = null;
    switch (data.type) {
        case TYPES.listener.type:
            if (data.once) {
                return [data.event];
            }
            return data.event;
        case TYPES.link.type:
            return new Enny.Handler({
                args: [data.link],
                handler: TYPES.link.handler
            }).toFlow();
        case TYPES.dataHandler.type:
        case TYPES.streamHandler.type:
            return new Enny.Handler({
                to: data.to,
                isStream: TYPES(data.type, TYPES.streamHandler),
                args: data.args,
                handler: data.handler
            }).toFlow();
        case TYPES.load.type:
            return new Enny.Handler({
                args: [[data.instance]],
                handler: TYPES.load.handler
            }).toFlow();
    }
};

// instance/method
// !instance/method
// >instance/method
// :instance/method
// method
Enny.parseMethod = function (input, defaultIns) {
    var output = {
        instance: defaultIns,
        type: TYPES.streamHandler
    };
    switch (input.charAt(0)) {
        case "!":
            output.type = TYPES.errorHandler;
            input = input.substr(1);
            break;
        case ":":
            output.type = TYPES.dataHandler;
            input = input.substr(1);
            break;
        case ">":
            output.disableInput = true;
            output.type = TYPES.streamHandler;
            input = input.substr(1);
            break;
        case "@":
            output.type = TYPES.link;
            input = input.substr(1);
            break;
        default:
            break;
    }

    var splits = input.split("/");
    if (splits.length === 2) {
        output.instance = splits[0];
        output.method = splits[1];
    } else {
        output.method = splits[0];
    }
    return output;
}

Enny.parseFlowComponent = function (_input, instName) {
    var input = Ul.clone(_input);

    if (Typpy(input, String)) {
        input = [input];
    }

    var output = {}
      , eP = null
      , mP = null
      ;

    // Load
    if (input[0] === TYPES.load.handler) {
        output.type = TYPES.load;
        output.args = input.slice(1);
    // Emit/link
    } else if ((eP = Enny.parseMethod(input[0], instName)).method === "flow") {
        if (TYPES((mP = Enny.parseMethod(input[1], instName)).type, TYPES.link)) {
            output = mP;
            output.type = TYPES.link;
        } else {
            output = eP;
            output.type = TYPES.emit;
            output.event = input[1];
        }
    }

    // Stream handler
    if (!output.type) {
        output = Enny.parseMethod(input[0], instName);
        output.args = input.slice(1);
    }

    return output;
};

Enny.instanceFlow = function (_input, name) {
    var output = {
        load: {},
        dataHandler: {},
        errorHandler: {},
        streamHandler: {},
        emit: {},
        listener: {}
    };

    if (!_input.length) {
        return output;
    }

    IterateObject(_input, function (f) {
        // Collect listeners
        output.listener[f[0]] = {
            event: f[0],
            type: TYPES.listener
        };
        IterateObject(f.slice(1), function (c) {
            c = Enny.parseFlowComponent(c, name);
            if (c.instance !== name) { return; }
            output[c.type][c.method] = c;
        });
    });
    return output;
};

Enny.parseFlow = function (_input, instName) {

    var out = {};

    IterateObject(_input, function (elm) {
        var ev = SetOrGet(out, elm[0], []);
        var p = [];
        IterateObject(elm.slice(1), function (comp) {
            p.push(Enny.parseFlowComponent(comp, instName));
        });
        ev.push(p);
    });

    return out;
};

Enny.convertToOn = function (input) {
    if (input.serverMethod || TYPES(input.type, TYPES.emit)) {
        return TYPES.listener;
    }
    return input.type;
};

Enny.TYPES = TYPES;

module.exports = Enny;
<|endoftext|>


<commit_before>'use strict';
/**
 * @file Easy access to AnyFetch API.
 *
 * @see http://anyFetch.com
 */
 // TODO: migrate to supertest
var request = require('supertest');
var async = require('async');
var util = require('util');
var fs = require('fs');

// TODO: wrap into an Anyfetch class
// TODO: Anyfetch.getAccessToken(APP_ID, APP_SECRET, code, function(err, accessToken)
// Use the access token from the Anyfetch object instance
var accessToken = process.env.ACCESS_TOKEN;

// TODO: make configurable
var apiHost = 'api.anyfetch.com';

/**
 * Will be used to automatically generate the simplest mapping functions
 * @see api.anyfetch.com/config/routes.js
 */
var defaultDescriptor = {
  expectedStatus: 200,
  verb: 'GET',
  requireId: false,
  params: null,
  body: null
}
// We'll read mapping descriptors from a JSON file
var apiDescriptorsFile = __dirname + '/apiDescriptors.json';
var aliasesFile = __dirname + '/aliases.json';

var generateMapping = function(config) {
  // `config` extends the default descriptor
  for(var i in defaultDescriptor) {
    if(!config[i])
      config[i] = defaultDescriptor[i];
  }

  /**
   * Example of accepted call syntaxes:
   * (depending on the requirements of the API endpoint)
   * apiMapping(cb)
   * apiMapping(id, cb)
   * apiMapping(body, cb)
   * apiMapping(id, body, cb)
   * apiMapping(id, params, cb)
   * apiMapping(params, cb)
   */
  return function apiMapping() {
    // Convert arguments to an array
    var args = [];
    for (var i in arguments)
      args.push(arguments[i]);

    // We must support quite a lot of different call syntaxes
    var params = {};
    var body = {};

    // cb is always the last parameter
    var cb = args.pop();

    if (config.body) {
      body = args.pop() || {};
      // Make sure that every field of the body is accepted
      for(var key in body) {
        if(config.body.indexOf(key) < 0) {
          return cb(new Error('Argument error, the key ' + key + ' is not allowed in this request\'s body'));
        }
      }
    }

    if (config.params) {
      params = args.pop() || {};
      // Make sure that every GET parameter is accepted
      for(var key in params) {
        if(config.params.indexOf(key) === -1) {
          return cb(new Error('Argument error, the key ' + key + ' is not allowed in this request\'s GET parameters'));
        }
      }
    }

    // id is always the first parameter (when it's actually required)
    if(config.requireId) {
      var id = args.pop();
      if(!isNaN(id)) {
        // Substitute id parameter in endpoint string
        config.endpoint = config.endpoint.replace('{id}', id);
      }
      else {
        return cb(new Error('Argument error, the first parameter must be a numeric id'));
      }
    }

    var options = {
      // TODO: make sure SSL is used
      host: apiHost,
      uri: config.endpoint,
      // Need to convert the verb to superagent method name
      method: (config.verb == 'DELETE') ? 'del' : config.verb.toLowerCase(),
      qs: params,
      body: JSON.stringify(body)
    };

    // Build request (using supertest)
    var r = request(options.host)[options.method](options.uri)
      .query(options.qs)
      .set('Authorization', 'Bearer ' + accessToken);
    if (config.body)
      r = r.send(options.body);
    r.expect(config.expectedStatus)
     .end(function(err, res) {
      cb(err, res.res.body);
     });
  };
};

async.waterfall([
  function readJsonDescriptors(cb) {
    fs.readFile(apiDescriptorsFile, 'utf8', cb);
  },
  function processJson(data, cb) {
    var mappingDescriptor = JSON.parse(data);

    // Generate the function for each endpoint
    var mappingFunctions = {};
    for (var name in mappingDescriptor) {
      mappingFunctions[name] = generateMapping(mappingDescriptor[name]);
    }

    cb(null, mappingFunctions);
  },
  function readJsonAliases(mappingFunctions, cb) {
    fs.readFile(aliasesFile, 'utf8', function(err, data) {
      cb(err, data, mappingFunctions);
    });
  },
  /**
   * Add nice semantic aliases
   * E.g. postSubcompany --> postSubcompanies
   * (What is actually done is to post ONE company, so it makes more sense)
   */
  function generateAliases(data, mappingFunctions, cb) {
    var aliasesJson = JSON.parse(data);
    for (var newName in aliasesJson) {
      mappingFunctions[newName] = mappingFunctions[aliasesJson[newName]];
    }

    cb(null, mappingFunctions);
  },
  /**
   * More complex syntax for API calls that are related to an element.
   * Examples:
   * - getDocumentById(123).getRelated(cb)
   * - getDocumentById(123).postFile(file, cb)
   * @warning getDocumentById(123, cb) is valid as well!
   */
  function generateAdvancedMappings(mappingFunctions, cb) {
    // ----- Documents
    var getDocumentByIdCb = mappingFunctions['getDocumentById'];
    mappingFunctions['getDocumentById'] = function() {
      // Invalid call syntax
      if (arguments.length > 2 || isNaN(arguments[0])) {
        // We assume the last argument is a callback
        arguments[arguments.length - 1](new Error('Invalid call syntax'));
      }
      var id = arguments[0];

      // Single-step call syntax
      // getDocumentById(123, cb)
      if (arguments.length == 2) {
        return getDocumentByIdCb(id, arguments[1]);
      }

      // Two-step call syntax
      // getDocumentById(123).getRelated(cb)
      return {
        getSimilar: generateMapping({ endpoint: '/documents/'+ id +'/similar' }),
        getRelated: generateMapping({ endpoint: '/documents/'+ id +'/related' }),
        getRaw: generateMapping({ endpoint: '/documents/'+ id +'/raw' }),
        getFile: generateMapping({ endpoint: '/documents/'+ id +'/file' }),
        postFile: function(file, cb) {
          // TODO
        }
      }
    }

    cb(null, mappingFunctions);
  }
  ],
  function(err, allMappings) {
    if (err) {
      // TODO: bubble up
      console.log(err);
      return;
    }

    // TODO: output
  }
);

// TODO: more complex syntax: getDocumentById(123).getRelated(cb);<commit_msg>postFile<commit_after>'use strict';
/**
 * @file Easy access to AnyFetch API.
 *
 * @see http://anyFetch.com
 */
 // TODO: migrate to supertest
var request = require('supertest');
var async = require('async');
var util = require('util');
var fs = require('fs');

// TODO: wrap into an Anyfetch class
// TODO: Anyfetch.getAccessToken(APP_ID, APP_SECRET, code, function(err, accessToken)
// Use the access token from the Anyfetch object instance
var accessToken = process.env.ACCESS_TOKEN;

// TODO: make configurable
var apiHost = 'api.anyfetch.com';
request = request(apiHost);

/**
 * Will be used to automatically generate the simplest mapping functions
 * @see api.anyfetch.com/config/routes.js
 */
var defaultDescriptor = {
  expectedStatus: 200,
  verb: 'GET',
  requireId: false,
  params: null,
  body: null
}
// We'll read mapping descriptors from a JSON file
var apiDescriptorsFile = __dirname + '/apiDescriptors.json';
var aliasesFile = __dirname + '/aliases.json';

var generateMapping = function(config) {
  // `config` extends the default descriptor
  for(var i in defaultDescriptor) {
    if(!config[i])
      config[i] = defaultDescriptor[i];
  }

  /**
   * Example of accepted call syntaxes:
   * (depending on the requirements of the API endpoint)
   * apiMapping(cb)
   * apiMapping(id, cb)
   * apiMapping(body, cb)
   * apiMapping(id, body, cb)
   * apiMapping(id, params, cb)
   * apiMapping(params, cb)
   */
  return function apiMapping() {
    // Convert arguments to an array
    var args = [];
    for (var i in arguments)
      args.push(arguments[i]);

    // We must support quite a lot of different call syntaxes
    var params = {};
    var body = {};

    // cb is always the last parameter
    var cb = args.pop();

    if (config.body) {
      body = args.pop() || {};
      // Make sure that every field of the body is accepted
      for(var key in body) {
        if(config.body.indexOf(key) < 0) {
          return cb(new Error('Argument error, the key ' + key + ' is not allowed in this request\'s body'));
        }
      }
    }

    if (config.params) {
      params = args.pop() || {};
      // Make sure that every GET parameter is accepted
      for(var key in params) {
        if(config.params.indexOf(key) === -1) {
          return cb(new Error('Argument error, the key ' + key + ' is not allowed in this request\'s GET parameters'));
        }
      }
    }

    // id is always the first parameter (when it's actually required)
    if(config.requireId) {
      var id = args.pop();
      if(!isNaN(id)) {
        // Substitute id parameter in endpoint string
        config.endpoint = config.endpoint.replace('{id}', id);
      }
      else {
        return cb(new Error('Argument error, the first parameter must be a numeric id'));
      }
    }

    var options = {
      // TODO: make sure SSL is used
      host: apiHost,
      uri: config.endpoint,
      // Need to convert the verb to superagent method name
      method: (config.verb == 'DELETE') ? 'del' : config.verb.toLowerCase(),
      qs: params,
      body: JSON.stringify(body)
    };

    // Build request (using supertest)
    var r = request[options.method](options.uri)
      .query(options.qs)
      .set('Authorization', 'Bearer ' + accessToken);
    if (config.body)
      r = r.send(options.body);
    r.expect(config.expectedStatus)
     .end(function(err, res) {
      cb(err, res.res.body);
     });
  };
};

async.waterfall([
  function readJsonDescriptors(cb) {
    fs.readFile(apiDescriptorsFile, 'utf8', cb);
  },
  function processJson(data, cb) {
    var mappingDescriptor = JSON.parse(data);

    // Generate the function for each endpoint
    var mappingFunctions = {};
    for (var name in mappingDescriptor) {
      mappingFunctions[name] = generateMapping(mappingDescriptor[name]);
    }

    cb(null, mappingFunctions);
  },
  function readJsonAliases(mappingFunctions, cb) {
    fs.readFile(aliasesFile, 'utf8', function(err, data) {
      cb(err, data, mappingFunctions);
    });
  },
  /**
   * Add nice semantic aliases
   * E.g. postSubcompany --> postSubcompanies
   * (What is actually done is to post ONE company, so it makes more sense)
   */
  function generateAliases(data, mappingFunctions, cb) {
    var aliasesJson = JSON.parse(data);
    for (var newName in aliasesJson) {
      mappingFunctions[newName] = mappingFunctions[aliasesJson[newName]];
    }

    cb(null, mappingFunctions);
  },
  /**
   * More complex syntax for API calls that are related to an element.
   * Examples:
   * - getDocumentById(123).getRelated(cb)
   * - getDocumentById(123).postFile(file, cb)
   * @warning getDocumentById(123, cb) is valid as well!
   */
  // TODO: same thing with getDocumentByIdentifier
  function generateAdvancedMappings(mappingFunctions, cb) {
    // ----- Documents
    var getDocumentByIdCb = mappingFunctions['getDocumentById'];
    mappingFunctions['getDocumentById'] = function() {
      // Invalid call syntax
      if (arguments.length > 2 || isNaN(arguments[0])) {
        // We assume the last argument is a callback
        arguments[arguments.length - 1](new Error('Invalid call syntax'));
      }
      var id = arguments[0];

      // Single-step call syntax
      // getDocumentById(123, cb)
      if (arguments.length == 2) {
        return getDocumentByIdCb(id, arguments[1]);
      }

      // Two-step call syntax
      // getDocumentById(123).getRelated(cb)
      return {
        // TODO: do not hardcode these endpoints
        getSimilar: generateMapping({ endpoint: '/documents/'+ id +'/similar' }),
        getRelated: generateMapping({ endpoint: '/documents/'+ id +'/related' }),
        getRaw: generateMapping({ endpoint: '/documents/'+ id +'/raw' }),
        getFile: generateMapping({ endpoint: '/documents/'+ id +'/file' }),
        /**
         * Add a file to a previously uploaded document
         *
         * @param {Object} Must at least contain a `file` key, which can either be a stream (e.g. `fs.createReadStream`) or a Buffer object. Can also contains a `contentType` key (for MIME type), and a `filename`.
         * @param {Function} cb Callback with error if any.
         * @Warning: unfortunately, due to the variety of Stream, we can't type-check, so unexpected errors will occur if you specify weird file parameters.
         */
        postFile: function(config, cb) {
          if(typeof(config) === 'function') {
            config = config();
          }
          if (!config.file) {
            return cb(new Error('The config parameter must contain a `file` key'));
          }

          var endpoint = '/documents/'+ id +'/file';
          var options = {
            filename: config.filename || '',
            contentType: config.contentType || ''
          };

          request.post(endpoint)
            .set('Authorization', 'Bearer ' + accessToken)
            .expect(204)
            .attach('file', config.file, options)
            .end(function(err, res) {
              cb(err, res.res.body);
            });
        }
      }
    }

    cb(null, mappingFunctions);
  }
  ],
  function(err, allMappings) {
    if (err) {
      // TODO: bubble up
      console.log(err);
      return;
    }

    // TODO: output functions
  }
);<|endoftext|>


<commit_before>var isBrowser = (typeof window !== 'undefined');
var Masonry = isBrowser ? window.Masonry || require('masonry') : null;
var imagesloaded = isBrowser ? require('imagesloaded') : null;
var refName = 'masonryContainer';

function extend() {
    var result = {};
    for (var i = 0; i < arguments.length; i++) {
        var keys = Object.keys(arguments[i]);
        for (var j = 0; j < keys.length; j++) {
            result[keys[j]] = arguments[i][keys[j]];
        }
    }
    return result;
}

function MasonryComponent(React) {
    return React.createClass({
        masonry: false,

        domChildren: [],

        displayName: 'MasonryComponent',

        propTypes: {
            disableImagesLoaded: React.PropTypes.bool,
            options: React.PropTypes.object
        },

        getDefaultProps: function() {
            return {
                disableImagesLoaded: false,
                options: {},
                className: '',
                elementType: 'div'
            };
        },

        initializeMasonry: function(force) {
            if (!this.masonry || force) {
                this.masonry = new Masonry(
                    this.refs[refName],
                    this.props.options
                );

                this.domChildren = this.getNewDomChildren();
            }
        },

        getNewDomChildren: function() {
            var node = this.refs[refName];
            var children = this.props.options.itemSelector ? node.querySelectorAll(this.props.options.itemSelector) : node.children;
            return Array.prototype.slice.call(children);
        },

        diffDomChildren: function() {
            var oldChildren = this.domChildren.filter(function(element) {
                /*
                 * take only elements attached to DOM
                 * (aka the parent is the masonry container, not null)
                 */
                return !!element.parentNode;
            });

            var newChildren = this.getNewDomChildren();

            var removed = oldChildren.filter(function(oldChild) {
                return !~newChildren.indexOf(oldChild);
            });

            var domDiff = newChildren.filter(function(newChild) {
                return !~oldChildren.indexOf(newChild);
            });

            var beginningIndex = 0;

            // get everything added to the beginning of the DOMNode list
            var prepended = domDiff.filter(function(newChild, i) {
                var prepend = (beginningIndex === newChildren.indexOf(newChild));

                if (prepend) {
                    // increase the index
                    beginningIndex++;
                }

                return prepend;
            });

            // we assume that everything else is appended
            var appended = domDiff.filter(function(el) {
                return prepended.indexOf(el) === -1;
            });

            /*
             * otherwise we reverse it because so we're going through the list picking off the items that
             * have been added at the end of the list. this complex logic is preserved in case it needs to be
             * invoked
             *
             * var endingIndex = newChildren.length - 1;
             *
             * domDiff.reverse().filter(function(newChild, i){
             *     var append = endingIndex == newChildren.indexOf(newChild);
             *
             *     if (append) {
             *         endingIndex--;
             *     }
             *
             *     return append;
             * });
             */

            // get everything added to the end of the DOMNode list
            var moved = [];

            if (removed.length === 0) {
                moved = oldChildren.filter(function(child, index) {
                    return index !== newChildren.indexOf(child);
                });
            }

            this.domChildren = newChildren;

            return {
                old: oldChildren,
                new: newChildren,
                removed: removed,
                appended: appended,
                prepended: prepended,
                moved: moved
            };
        },

        performLayout: function() {
            var diff = this.diffDomChildren();

            if (diff.removed.length > 0) {
                this.masonry.remove(diff.removed);
                this.masonry.reloadItems();
            }

            if (diff.appended.length > 0) {
                this.masonry.appended(diff.appended);
                this.masonry.reloadItems();
            }

            if (diff.prepended.length > 0) {
                this.masonry.prepended(diff.prepended);
            }

            if (diff.moved.length > 0) {
                this.masonry.reloadItems();
            }

            this.masonry.layout();
        },

        imagesLoaded: function() {
            if (this.props.disableImagesLoaded) return;

            imagesloaded(
                this.refs[refName],
                function(instance) {
                    this.masonry.layout();
                }.bind(this)
            );
        },

        componentDidMount: function() {
            this.initializeMasonry();
            this.imagesLoaded();
        },

        componentDidUpdate: function() {
            this.performLayout();
            this.imagesLoaded();
        },

        componentWillReceiveProps: function() {
            this._timer = setTimeout(function() {
                this.masonry.reloadItems();
                this.isMounted && this.isMounted() && this.forceUpdate();
            }.bind(this), 0);
        },

        componentWillUnmount: function() {
            clearTimeout(this._timer);
        },

        render: function() {
            return React.createElement(this.props.elementType, extend({
                ref: refName
            }), this.props.children);
        }
    })
}

module.exports = MasonryComponent;
<commit_msg>fix merge<commit_after>var isBrowser = (typeof window !== 'undefined');
var Masonry = isBrowser ? window.Masonry || require('masonry') : null;
var imagesloaded = isBrowser ? require('imagesloaded') : null;
var refName = 'masonryContainer';

function extend() {
    var result = {};
    for (var i = 0; i < arguments.length; i++) {
        var keys = Object.keys(arguments[i]);
        for (var j = 0; j < keys.length; j++) {
            result[keys[j]] = arguments[i][keys[j]];
        }
    }
    return result;
}

function MasonryComponent(React) {
    return React.createClass({
        masonry: false,

        domChildren: [],

        displayName: 'MasonryComponent',

        propTypes: {
            disableImagesLoaded: React.PropTypes.bool,
            options: React.PropTypes.object
        },

        getDefaultProps: function() {
            return {
                disableImagesLoaded: false,
                options: {},
                className: '',
                elementType: 'div'
            };
        },

        initializeMasonry: function(force) {
            if (!this.masonry || force) {
                this.masonry = new Masonry(
                    this.refs[refName],
                    this.props.options
                );

                this.domChildren = this.getNewDomChildren();
            }
        },

        getNewDomChildren: function() {
            var node = this.refs[refName];
            var children = this.props.options.itemSelector ? node.querySelectorAll(this.props.options.itemSelector) : node.children;
            return Array.prototype.slice.call(children);
        },

        diffDomChildren: function() {
            var oldChildren = this.domChildren.filter(function(element) {
                /*
                 * take only elements attached to DOM
                 * (aka the parent is the masonry container, not null)
                 */
                return !!element.parentNode;
            });

            var newChildren = this.getNewDomChildren();

            var removed = oldChildren.filter(function(oldChild) {
                return !~newChildren.indexOf(oldChild);
            });

            var domDiff = newChildren.filter(function(newChild) {
                return !~oldChildren.indexOf(newChild);
            });

            var beginningIndex = 0;

            // get everything added to the beginning of the DOMNode list
            var prepended = domDiff.filter(function(newChild, i) {
                var prepend = (beginningIndex === newChildren.indexOf(newChild));

                if (prepend) {
                    // increase the index
                    beginningIndex++;
                }

                return prepend;
            });

            // we assume that everything else is appended
            var appended = domDiff.filter(function(el) {
                return prepended.indexOf(el) === -1;
            });

            /*
             * otherwise we reverse it because so we're going through the list picking off the items that
             * have been added at the end of the list. this complex logic is preserved in case it needs to be
             * invoked
             *
             * var endingIndex = newChildren.length - 1;
             *
             * domDiff.reverse().filter(function(newChild, i){
             *     var append = endingIndex == newChildren.indexOf(newChild);
             *
             *     if (append) {
             *         endingIndex--;
             *     }
             *
             *     return append;
             * });
             */

            // get everything added to the end of the DOMNode list
            var moved = [];

            if (removed.length === 0) {
                moved = oldChildren.filter(function(child, index) {
                    return index !== newChildren.indexOf(child);
                });
            }

            this.domChildren = newChildren;

            return {
                old: oldChildren,
                new: newChildren,
                removed: removed,
                appended: appended,
                prepended: prepended,
                moved: moved
            };
        },

        performLayout: function() {
            var diff = this.diffDomChildren();

            if (diff.removed.length > 0) {
                this.masonry.remove(diff.removed);
                this.masonry.reloadItems();
            }

            if (diff.appended.length > 0) {
                this.masonry.appended(diff.appended);
                this.masonry.reloadItems();
            }

            if (diff.prepended.length > 0) {
                this.masonry.prepended(diff.prepended);
            }

            if (diff.moved.length > 0) {
                this.masonry.reloadItems();
            }

            this.masonry.layout();
        },

        imagesLoaded: function() {
            if (this.props.disableImagesLoaded) return;

            imagesloaded(
                this.refs[refName],
                function(instance) {
                    this.masonry.layout();
                }.bind(this)
            );
        },

        componentDidMount: function() {
            this.initializeMasonry();
            this.imagesLoaded();
        },

        componentDidUpdate: function() {
            this.performLayout();
            this.imagesLoaded();
        },

        componentWillReceiveProps: function() {
            this._timer = setTimeout(function() {
                this.masonry.reloadItems();
                this.isMounted && this.isMounted() && this.forceUpdate();
            }.bind(this), 0);
        },

        componentWillUnmount: function() {
            clearTimeout(this._timer);
        },

        render: function() {
            return React.createElement(this.props.elementType, extend({
                ref: refName
            }, this.props), this.props.children);
        }
    })
}

module.exports = MasonryComponent;
<|endoftext|>


<commit_before>/**
*
*	OPENTSDB: Datum
*
*
*	DESCRIPTION:
*		- Factory for individual OpenTSDB data points.
*
*
*	NOTES:
*		[1]
*
*
*	TODO:
*		[1]
*
*
*	LICENSE:
*		MIT
*
*	Copyright (c) 2014. Athan Reines.
*
*
*	AUTHOR:
*		Athan Reines. kgryte@gmail.com.
*
*/

(function() {
	'use strict';

	// MODULES //

	var // Time format validation:
		validate = require( 'opentsdb-validate-time' );

	// DATUM //

	/**
	* FUNCTION: Datum()
	*	OpenTSDB datum contructor.
	*
	* @constructor
	* @returns {Datum} Datum instance
	*/
	function Datum() {
		// Metric (required):
		this._metric = null;

		// Timestamp (required):
		this._timestamp = null;

		// Value (required):
		this._value = null;

		// Tags (optional):
		this._tags = {};

		return this;
	} // end FUNCTION Datum()

	/**
	* METHOD: metric( metric )
	*	Metric name setter and getter. If a metric is supplied, sets the metric name. If no metric is supplied, returns the metric name.
	*
	* @param {String} [metric] - metric name; e.g., 'cpu.utilization'
	* @returns {Datum|String} Datum instance or metric name
	*/
	Datum.prototype.metric = function( metric ) {
		if ( !arguments.length ) {
			return this._metric;
		}
		if ( typeof metric !== 'string' ) {
			throw new Error( 'metric()::invalid input argument. Metric name must be a string.' );
		}
		this._metric = metric;
		return this;
	}; // end METHOD metric()

	/**
	* METHOD: timestamp( value )
	*	Timestamp setter and getter. If a value is provided, sets the timestamp. If no value is provided, returns the timestamp.
	*
	* @param {String|Number} [value] - timestamp; may be either an absolute time string or a UNIX timestamp
	* @returns {Datum|Number} Datum instance or timestamp
	*/
	Datum.prototype.timestamp = function( value ) {
		if ( !arguments.length ) {
			return this._timestamp;
		}
		if ( typeof value !== 'string' && ( typeof value !== 'number' || value !== value ) ) {
			throw new Error( 'timestamp()::invalid input argument. Timestamp must be either a string or numeric.' );
		}
		if ( !validate.format( value ) ) {
			throw new Error( 'timestamp()::invalid input argument. Timestamp must be a valid time.' );
		}
		this._timestamp = value;
		return this;
	}; // end METHOD timestamp()

	/**
	* METHOD: value( value )
	*	Value setter and getter. If a value is supplied, sets the datum value. If no value is supplied, returns the datum value.
	*
	* @param {Number} [value] - datum value
	* @returns {Datum|Number} Datum instance or value
	*/
	Datum.prototype.value = function( value ) {
		if ( !arguments.length ) {
			return this._value;
		}
		if ( typeof value !== 'number' || value !== value ) {
			throw new Error( 'value()::invalid input argument. Value must be numeric.' );
		}
		this._value = value;
		return this;
	}; // end METHOD value()

	/**
	* METHOD: tags( tag, value )
	*	Tag value setter and getter. If a value is supplied, sets the tag value. If no value is supplied, gets the tag value. If the tag name has not been set, getting the tag value returns undefined. If no tag name-value pair is provided, returns all tags. NOTE: the returned object for all tags does not correspond to the internal object. Accordingly, the internal object should not be treated as mutable.
	*
	* @param {String} [tag] - tag name
	* @param {String} [value] - tag value
	* @returns {Datum|Object|String|undefined} Datum instance, all tags, or tag value
	*/
	Datum.prototype.tags = function( tag, value ) {
		var numArgs = arguments.length,
			keys = Object.keys( this._tags ),
			key,
			tags = {};
		if ( !numArgs ) {
			for ( var i = 0; i < keys.length; i++ ) {
				key = keys[ i ];
				tags[ key ] = this._tags[ key ];
			}
			return tags;
		}
		if ( typeof tag !== 'string' ) {
			throw new Error( 'tag()::invalid input argument. Tag name must be a string.' );
		}
		if ( numArgs === 1 ) {
			return this._tags[ tag ];
		}
		if ( typeof value !== 'string' ) {
			throw new Error( 'tag()::invalid input argument. Tag value must be a string.' );
		}
		this._tags[ tag ] = value;
		return this;
	}; // end METHOD tags()

	/**
	* METHOD: dtag( tag )
	*	Removes a tag.
	*
	* @param {String} tag - tag name
	* @returns {Datum} Datum instance
	*/
	Datum.prototype.dtag = function( tag ) {
		if ( !arguments.length ) {
			throw new Error( 'dtag()::insufficient input arguments. Must provide a tag name' );
		}
		if ( typeof tag !== 'string' ) {
			throw new Error( 'dtag()::invalid input argument. Tag name must be a string.' );
		}
		delete this._tags[ tag ];
		return this;
	}; // end METHOD tag()

	/**
	* METHOD: toString()
	*	Custom `toString()` method which serializes a datum. Format:
	*	"metric timestamp value tagk1=tagv1 tagk2=tagkN ... tagkN=tagvN"
	*
	* @returns {String} serialized datum
	*/
	Datum.prototype.toString = function() {
		var tags = this._tags,
			keys,
			numTags,
			key,
			buffer;

		if ( !this._metric ) {
			throw new Error( 'toString()::invalid datum. Datum must be assigned a `metric` name.' );
		}
		if ( !this._timestamp && this._timestamp !== 0) {
			throw new Error( 'toString()::invalid datum. Datum must be assigned a `timestamp`.' );
		}
		if ( !this._value && this._value !== 0 ) {
			throw new Error( 'toString()::invalid datum. Datum must be assigned a `value`.' );
		}
		// Count the tags:
		keys = Object.keys( tags );
		numTags = keys.length;

		if ( numTags < 1 ) {
			throw new Error( 'toString()::invalid datum. Datum must have at least one `tag`.' );
		}

		// Create a new array buffer:
		buffer = new Array( 3+numTags );
		buffer[ 0 ] = this._metric;
		buffer[ 1 ] = this._timestamp;
		buffer[ 2 ] = this._value;

		// If we have tags, process them...
		for ( var i = 0; i < numTags; i++ ) {
			key = keys[ i ];
			buffer[ i+3 ] = key + '=' + tags[ key ];
		}
		return buffer.join( ' ' );
	}; // end METHOD toString()

	// EXPORTS //

	module.exports = function newDatum(){
		return new Datum();
	};

})();<commit_msg>Remove file preamble<commit_after>'use strict';

// MODULES //

var validate = require( 'opentsdb-validate-time' );

// DATUM //

/**
* FUNCTION: Datum()
*	OpenTSDB datum contructor.
*
* @constructor
* @returns {Datum} Datum instance
*/
function Datum() {
	if ( !( this instanceof Datum ) ) {
		return new Datum();
	}
	// Metric (required):
	this._metric = null;

	// Timestamp (required):
	this._timestamp = null;

	// Value (required):
	this._value = null;

	// Tags (optional):
	this._tags = {};

	return this;
} // end FUNCTION Datum()

/**
* METHOD: metric( metric )
*	Metric name setter and getter. If a metric is supplied, sets the metric name. If no metric is supplied, returns the metric name.
*
* @param {String} [metric] - metric name; e.g., 'cpu.utilization'
* @returns {Datum|String} Datum instance or metric name
*/
Datum.prototype.metric = function( metric ) {
	if ( !arguments.length ) {
		return this._metric;
	}
	if ( typeof metric !== 'string' ) {
		throw new Error( 'metric()::invalid input argument. Metric name must be a string.' );
	}
	this._metric = metric;
	return this;
}; // end METHOD metric()

/**
* METHOD: timestamp( value )
*	Timestamp setter and getter. If a value is provided, sets the timestamp. If no value is provided, returns the timestamp.
*
* @param {String|Number} [value] - timestamp; may be either an absolute time string or a UNIX timestamp
* @returns {Datum|Number} Datum instance or timestamp
*/
Datum.prototype.timestamp = function( value ) {
	if ( !arguments.length ) {
		return this._timestamp;
	}
	if ( typeof value !== 'string' && ( typeof value !== 'number' || value !== value ) ) {
		throw new Error( 'timestamp()::invalid input argument. Timestamp must be either a string or numeric.' );
	}
	if ( !validate.format( value ) ) {
		throw new Error( 'timestamp()::invalid input argument. Timestamp must be a valid time.' );
	}
	this._timestamp = value;
	return this;
}; // end METHOD timestamp()

/**
* METHOD: value( value )
*	Value setter and getter. If a value is supplied, sets the datum value. If no value is supplied, returns the datum value.
*
* @param {Number} [value] - datum value
* @returns {Datum|Number} Datum instance or value
*/
Datum.prototype.value = function( value ) {
	if ( !arguments.length ) {
		return this._value;
	}
	if ( typeof value !== 'number' || value !== value ) {
		throw new Error( 'value()::invalid input argument. Value must be numeric.' );
	}
	this._value = value;
	return this;
}; // end METHOD value()

/**
* METHOD: tags( tag, value )
*	Tag value setter and getter. If a value is supplied, sets the tag value. If no value is supplied, gets the tag value. If the tag name has not been set, getting the tag value returns undefined. If no tag name-value pair is provided, returns all tags. NOTE: the returned object for all tags does not correspond to the internal object. Accordingly, the internal object should not be treated as mutable.
*
* @param {String} [tag] - tag name
* @param {String} [value] - tag value
* @returns {Datum|Object|String|undefined} Datum instance, all tags, or tag value
*/
Datum.prototype.tags = function( tag, value ) {
	var numArgs = arguments.length,
		keys = Object.keys( this._tags ),
		key,
		tags = {};
	if ( !numArgs ) {
		for ( var i = 0; i < keys.length; i++ ) {
			key = keys[ i ];
			tags[ key ] = this._tags[ key ];
		}
		return tags;
	}
	if ( typeof tag !== 'string' ) {
		throw new Error( 'tag()::invalid input argument. Tag name must be a string.' );
	}
	if ( numArgs === 1 ) {
		return this._tags[ tag ];
	}
	if ( typeof value !== 'string' ) {
		throw new Error( 'tag()::invalid input argument. Tag value must be a string.' );
	}
	this._tags[ tag ] = value;
	return this;
}; // end METHOD tags()

/**
* METHOD: dtag( tag )
*	Removes a tag.
*
* @param {String} tag - tag name
* @returns {Datum} Datum instance
*/
Datum.prototype.dtag = function( tag ) {
	if ( !arguments.length ) {
		throw new Error( 'dtag()::insufficient input arguments. Must provide a tag name' );
	}
	if ( typeof tag !== 'string' ) {
		throw new Error( 'dtag()::invalid input argument. Tag name must be a string.' );
	}
	delete this._tags[ tag ];
	return this;
}; // end METHOD tag()

/**
* METHOD: toString()
*	Custom `toString()` method which serializes a datum. Format:
*	"metric timestamp value tagk1=tagv1 tagk2=tagkN ... tagkN=tagvN"
*
* @returns {String} serialized datum
*/
Datum.prototype.toString = function() {
	var tags = this._tags,
		keys,
		numTags,
		key,
		buffer;

	if ( !this._metric ) {
		throw new Error( 'toString()::invalid datum. Datum must be assigned a `metric` name.' );
	}
	if ( !this._timestamp && this._timestamp !== 0) {
		throw new Error( 'toString()::invalid datum. Datum must be assigned a `timestamp`.' );
	}
	if ( !this._value && this._value !== 0 ) {
		throw new Error( 'toString()::invalid datum. Datum must be assigned a `value`.' );
	}
	// Count the tags:
	keys = Object.keys( tags );
	numTags = keys.length;

	if ( numTags < 1 ) {
		throw new Error( 'toString()::invalid datum. Datum must have at least one `tag`.' );
	}

	// Create a new array buffer:
	buffer = new Array( 3+numTags );
	buffer[ 0 ] = this._metric;
	buffer[ 1 ] = this._timestamp;
	buffer[ 2 ] = this._value;

	// If we have tags, process them...
	for ( var i = 0; i < numTags; i++ ) {
		key = keys[ i ];
		buffer[ i+3 ] = key + '=' + tags[ key ];
	}
	return buffer.join( ' ' );
}; // end METHOD toString()

// EXPORTS //

module.exports = function newDatum(){
	return new Datum();
};
<|endoftext|>


<commit_before>/* @flow */

import defaults from 'lodash.defaults';
import recurseTree from 'recurserator/recurseTree';

export default class ESTreeRunner {
  constructor(options: Object = {}) {
    this.options = defaults(options, {
      parentKey: Symbol()
    });
  }

  * run(startNode: Object, yieldFilter?: Function = ESTreeRunner.isNode, recursionFilter?: Function = ESTreeRunner.isNode): Iterator {
    for (let [key, node, path, parent] of recurseTree(startNode, yieldFilter, recursionFilter)) {
      if (this.parentKey !== null) {
        Reflect.defineProperty(node, this.parentKey, { value: parent });
      }

      yield node;
    }
  }

  * runUntil(filter: Function, startNode: Object): Iterator {
    for (let [key, node, path, parent] of recurseTree(startNode, ESTreeRunner.isNode, ESTreeRunner.isNode)) {
      if (filter(node, parent)) {
        yield node;
        break;
      }
    }
  }

  * runUntilType(type: string, startNode: Object): Iterator {
    yield* this.runUntil((node: Object) => node.type === type, startNode);
  }

  static isNode(node: Object) {
    return typeof node.type === 'string';
  }
}
<commit_msg>fix(run): issue with default params and generators in babel<commit_after>/* @flow */

import defaults from 'lodash.defaults';
import recurseTree from 'recurserator/recurseTree';

export default class ESTreeRunner {
  constructor(options: Object = {}) {
    this.options = defaults(options, {
      parentKey: Symbol()
    });
  }

  * run(startNode: Object, yieldFilter?: Function, recursionFilter?: Function): Iterator {
    yieldFilter = yieldFilter || ESTreeRunner.isNode;
    recursionFilter = recursionFilter || ESTreeRunner.isNode;

    for (let [key, node, path, parent] of recurseTree(startNode, yieldFilter, recursionFilter)) {
      if (this.parentKey !== null) {
        Reflect.defineProperty(node, this.parentKey, { value: parent });
      }

      yield node;
    }
  }

  * runUntil(filter: Function, startNode: Object): Iterator {
    for (let [key, node, path, parent] of recurseTree(startNode, ESTreeRunner.isNode, ESTreeRunner.isNode)) {
      if (filter(node, parent)) {
        yield node;
        break;
      }
    }
  }

  * runUntilType(type: string, startNode: Object): Iterator {
    yield* this.runUntil((node: Object) => node.type === type, startNode);
  }

  static isNode(node: Object) {
    return typeof node.type === 'string';
  }
}
<|endoftext|>