<commit_before>/*jslint node: true, vars: true, nomen: true, esversion: 6 */
'use strict';

const express = require('express');
const Http = require('http');
const debug = require('debug')('xpl-db:server');
const async = require('async');
const bodyParser = require('body-parser');
const serve_static = require('serve-static');
const compression = require('compression');

const NO_CACHE_CONTROL = "no-cache, private, no-store, must-revalidate, max-stale=0, max-age=1,post-check=0, pre-check=0";

class Server {
  constructor(configuration, store, xpl, memcached) {
    this.configuration = configuration || {};
    this.store = store;
    this.xpl = xpl;
    this._memcached=memcached;

    if (this.configuration.express) {
      this.app = this.configuration.express;

    } else {
      var app = express();
      this.app = app;
      app.enable('etag');
      app.use(compression());
      app.use(bodyParser.json());
      app.use(bodyParser.urlencoded({
        extended: true
      }));
    }
  }

  listen(callback) {
    var app = this.app;
// app.use(noCache);

    app.get(/^\/last\/(.*)$/, this._getLast.bind(this));
    app.get(/^\/history\/(.*)$/, this._getHistory.bind(this));
    app.get(/^\/minMaxAvgSum\/(.*)$/, this._getMinMaxAvgSum.bind(this));

    if (this.xpl) {
      app.get(/^\/xplCommand\/(.*)$/, this._xplCommand.bind(this));
      app.get(/^\/tunnelCommands(.*)$/, this._proxyCommands.bind(this));
    }

    app.post('/last', this._postLast.bind(this));
    app.post('/history', this._postHistory.bind(this));
    app.post('/minMaxAvgSum', this._postMinMaxAvgSum.bind(this));

    if (this.configuration.configPath) {

      var oneYear = 1000*60*60*24*365;

      app.use(express.static(__dirname + '/public', {  }));

      app.use("/config", serve_static(this.configuration.configPath, {
        index : false,
        maxAge: oneYear
      }));
    }

    app.use(function(req, res, next) {
      res.status(404).send('Sorry cant find that!');
    });

    var server = app.listen(this.configuration.httpPort || 8480, (error) => {
      if (error) {
        console.error("Server can not listen", error);
        return;
      }
      debug("listen", "Server is listening ", server.address());

      callback(server);
    });
  }

  _proxyCommands(request, response) {
    var hs = {
        'Content-Type': 'application/json',
        'Transfer-Encoding': 'chunked',
        'Cache-Control': NO_CACHE_CONTROL
    };
    response.writeHead(200, hs);

    var cb = (message) => {
      var json=JSON.stringify(message);
      debug("_proxyCommands", "Send json",json);
      response.write(json);
    };

    this.xpl.on("message", cb);

    response.on('error', (error) => {
      console.error("Catch error !");

      this.xpl.removeListener("message", cb);
    });

    response.on('close', () => {
      console.error("Catch close, remove listener !");

      this.xpl.removeListener("message", cb);
    });
  }

  _xplCommand(request, response) {
    var key = request.params[0];

    var query = request.query;
    var command = query.c || query.cmd || query.command;
    var device = query.device;
    var target = query.target || "*";
    var bodyName = query.bodyName || "delabarre.command";
    var current = query.v || query.current;

    if (!device && !command) {
      var reg=/(.*)\/([^/]+)$/.exec(key);
      if (reg) {
        device=reg[1];
        command=reg[2];
      }
    }

    debug("xplCommand",
        "key=", key,
        "command=", command,
        "device=",device,
        "target=",target,
        "bodyName=",bodyName,
        "current=",current);

    if (!device || !command) {
      response.status(404).send("Device or command not found");
      return;
    }

    var source="http."+request.connection.remoteAddress;

    var params={
        command: command,
        device: device
    };
    if (current!==undefined) {
      params.current=current;
    }

    this.xpl.sendXplCmnd(params, bodyName, target, source, (error) => {

      if (error) {
        console.error("Command is not sent",error);
        response.status(500).send("Internal error");
        return;
      }

      console.log("Command sent !");
      response.status(200).send("Command sent");
    });
  }

  _set(name, request, response, func) {
    var keys = Object.keys(request.body);
    debug("_set", name, "set keys=", keys);

    var options = formatOptions(request);

    var results = {};
    var lastDate=null;

    async.eachLimit(keys, 8, (key, callback) => {
      var reg=/(.*)\/([^/]+)$/.exec(key);
      if (reg) {
        key=reg[1]+"@"+reg[2]; // Transform @ to /
      }

      func.call(this.store, key, options, (error, value) => {
        debug("_set", name, " set key=", key, "value=", value, "error=", error);
        if (error) {
          console.error("Can not process name=",name,"key=",key,"error=",error);
          return callback();
        }

        var reg2=/(.*)\@([^@]+)$/.exec(key);
        if (reg2) {
          key=reg2[1]+"/"+reg[2]; // Transform / to @
        }

        results[key] = value;

        if (value.date) {
          if (!lastDate || lastDate<value.date) {
            lastDate=value.date;
          }
        }

        callback();
      });

    }, (error) => {
      if (error) {
        // send 500
        if (error.code === 'NOT_FOUND') {
          response.status(404).send("Key '" + error.key + "' not found");
          return;
        }

        response.status(500).send(String(error));
        return;
      }

      if (lastDate) {
        if (!response.headersSent) {
          var since=request.headers['if-modified-since'];
          console.log("Since=",since,"/",lastDate);

          if (since && (new Date(since)).getTime()===lastDate.getTime()) {
            response.status(304).send("Not modified");
            return;
          }
        }

        response.setHeader("Last-Modified", lastDate.toUTCString());
      }

      response.json(results);
    });
  }

  _get(name, request, response, func, noMemcached) {
    if (noMemcached===undefined) {
      var h=request.headers['x-memcached'];

      noMemcached=(h && h.toLowerCase()=='false');
    }
    var key = request.params[0];
    debug("_get", "type=", name, "key=", key, "noMemcached=",noMemcached);

    if (!noMemcached && name=="getLast") {
      if (this._memcached) {
        debug("_get", "Seach in memcached");

        this._memcached.getCurrent(key, (error, value) => {
          debug("_get", "Memcache returns value=",value,"error=",error);
          if (!error && value) {
            response.json(value);
            return;
          }

          this._get(name, request, response, func, true);
        });
        return;
      }
    }

    var reg=/(.*)\/([^/]+)$/.exec(key);
    if (reg) {
      key=reg[1]+"@"+reg[2]; // Transform @ to /
    }

    var options = formatOptions(request);

    func.call(this.store, key, options, (error, values) => {
      debug("_get", "type=", name, "key=", key, "values=", values);
      if (error) {
        // send 500
        if (error.code === 'NOT_FOUND') {
          response.status(404).send('Key not found');
          return;
        }

        response.status(500).send(String(error));
        return;
      }

      response.json(values);
    });
  }

  _getLast(request, response) {
    this._get("getLast", request, response, this.store.getLast);
  }

  _getHistory(request, response) {
    this._get("getHistory", request, response, this.store.getHistory);
  }

  _getMinMaxAvgSum(request, response) {
    this._get("getMinMaxAvgSum", request, response, this.store.getMinMaxAvgSum);
  }

  _postLast(request, response) {
    this._set("getLastSet", request, response, this.store.getLast);
  }

  _postHistory(request, response) {
    this._set("getHistorySet", request, response, this.store.getHistory);
  }

  _postMinMaxAvgSum(request, response) {
    this._set("getMinMaxAvgSumSet", request, response, this.store.getMinMaxAvgSum);
  }
}

function formatOptions(request) {
  var ret = {};

  var query = request.query;
  if (query.limit) {
    ret.limit = parseInt(query.limit, 10);
  }

  if (query.minDate) {
    ret.minDate = new Date(query.minDate);
  }

  if (query.maxDate) {
    ret.maxDate = new Date(query.maxDate);
  }

  if (query.averageMs) {
    ret.averageMs = parseInt(query.averageMs, 10);
  }

  if (query.step) {
    ret.stepMs = parseInt(query.step, 10) * 1000;
  }

  return ret;
}

module.exports = Server;
<commit_msg>Improve memcache<commit_after>/*jslint node: true, vars: true, nomen: true, esversion: 6 */
'use strict';

const express = require('express');
const Http = require('http');
const debug = require('debug')('xpl-db:server');
const async = require('async');
const bodyParser = require('body-parser');
const serve_static = require('serve-static');
const compression = require('compression');

const NO_CACHE_CONTROL = "no-cache, private, no-store, must-revalidate, max-stale=0, max-age=1,post-check=0, pre-check=0";

class Server {
  constructor(configuration, store, xpl, memcached) {
    this.configuration = configuration || {};
    this.store = store;
    this.xpl = xpl;
    this._memcached=memcached;

    if (this.configuration.express) {
      this.app = this.configuration.express;

    } else {
      var app = express();
      this.app = app;
      app.enable('etag');
      app.use(compression());
      app.use(bodyParser.json());
      app.use(bodyParser.urlencoded({
        extended: true
      }));
    }
  }

  listen(callback) {
    var app = this.app;
// app.use(noCache);

    app.get(/^\/last\/(.*)$/, this._getLast.bind(this));
    app.get(/^\/history\/(.*)$/, this._getHistory.bind(this));
    app.get(/^\/minMaxAvgSum\/(.*)$/, this._getMinMaxAvgSum.bind(this));

    if (this.xpl) {
      app.get(/^\/xplCommand\/(.*)$/, this._xplCommand.bind(this));
      app.get(/^\/tunnelCommands(.*)$/, this._proxyCommands.bind(this));
    }

    app.post('/last', this._postLast.bind(this));
    app.post('/history', this._postHistory.bind(this));
    app.post('/minMaxAvgSum', this._postMinMaxAvgSum.bind(this));

    if (this.configuration.configPath) {

      var oneYear = 1000*60*60*24*365;

      app.use(express.static(__dirname + '/public', {  }));

      app.use("/config", serve_static(this.configuration.configPath, {
        index : false,
        maxAge: oneYear
      }));
    }

    app.use(function(req, res, next) {
      res.status(404).send('Sorry cant find that!');
    });

    var server = app.listen(this.configuration.httpPort || 8480, (error) => {
      if (error) {
        console.error("Server can not listen", error);
        return;
      }
      debug("listen", "Server is listening ", server.address());

      callback(null, server);
    });
  }

  _proxyCommands(request, response) {
    var hs = {
        'Content-Type': 'application/json',
        'Transfer-Encoding': 'chunked',
        'Cache-Control': NO_CACHE_CONTROL
    };
    response.writeHead(200, hs);

    var cb = (message) => {
      var json=JSON.stringify(message);
      debug("_proxyCommands", "Send json",json);
      response.write(json);
    };

    this.xpl.on("message", cb);

    response.on('error', (error) => {
      console.error("Catch error !");

      this.xpl.removeListener("message", cb);
    });

    response.on('close', () => {
      console.error("Catch close, remove listener !");

      this.xpl.removeListener("message", cb);
    });
  }

  _xplCommand(request, response) {
    var key = request.params[0];

    var query = request.query;
    var command = query.c || query.cmd || query.command;
    var device = query.device;
    var target = query.target || "*";
    var bodyName = query.bodyName || "delabarre.command";
    var current = query.v || query.current;

    if (!device && !command) {
      var reg=/(.*)\/([^/]+)$/.exec(key);
      if (reg) {
        device=reg[1];
        command=reg[2];
      }
    }

    debug("xplCommand",
        "key=", key,
        "command=", command,
        "device=",device,
        "target=",target,
        "bodyName=",bodyName,
        "current=",current);

    if (!device || !command) {
      response.status(404).send("Device or command not found");
      return;
    }

    var source="http."+request.connection.remoteAddress;

    var params={
        command: command,
        device: device
    };
    if (current!==undefined) {
      params.current=current;
    }

    this.xpl.sendXplCmnd(params, bodyName, target, source, (error) => {

      if (error) {
        console.error("Command is not sent",error);
        response.status(500).send("Internal error");
        return;
      }

      console.log("Command sent !");
      response.status(200).send("Command sent");
    });
  }

  _set(name, request, response, func) {
    var keys = Object.keys(request.body);
    debug("_set", name, "set keys=", keys);

    var options = formatOptions(request);

    var results = {};
    var lastDate=null;

    async.eachLimit(keys, 8, (key, callback) => {
      var reg=/(.*)\/([^/]+)$/.exec(key);
      if (reg) {
        key=reg[1]+"@"+reg[2]; // Transform @ to /
      }

      func.call(this.store, key, options, (error, value) => {
        debug("_set", name, " set key=", key, "value=", value, "error=", error);
        if (error) {
          console.error("Can not process name=",name,"key=",key,"error=",error);
          return callback();
        }

        var reg2=/(.*)\@([^@]+)$/.exec(key);
        if (reg2) {
          key=reg2[1]+"/"+reg[2]; // Transform / to @
        }

        results[key] = value;

        if (value.date) {
          if (!lastDate || lastDate<value.date) {
            lastDate=value.date;
          }
        }

        callback();
      });

    }, (error) => {
      if (error) {
        // send 500
        if (error.code === 'NOT_FOUND') {
          response.status(404).send("Key '" + error.key + "' not found");
          return;
        }

        response.status(500).send(String(error));
        return;
      }

      if (lastDate) {
        if (!response.headersSent) {
          var since=request.headers['if-modified-since'];
          console.log("Since=",since,"/",lastDate);

          if (since && (new Date(since)).getTime()===lastDate.getTime()) {
            response.status(304).send("Not modified");
            return;
          }
        }

        response.setHeader("Last-Modified", lastDate.toUTCString());
      }

      response.json(results);
    });
  }

  _get(name, request, response, func, noMemcached) {
    if (noMemcached===undefined) {
      var h=request.headers['x-memcached'];

      noMemcached=(h && h.toLowerCase()=='false');
    }
    var key = request.params[0];
    debug("_get", "type=", name, "key=", key, "noMemcached=",noMemcached);

    if (!noMemcached && name=="getLast") {
      if (this._memcached) {
        debug("_get", "Seach in memcached");

        this._memcached.getCurrent(key, (error, value) => {
          debug("_get", "Memcache returns value=",value,"error=",error);
          if (!error && value) {
            response.json(value);
            return;
          }

          this._get(name, request, response, func, true);
        });
        return;
      }
    }

    var reg=/(.*)\/([^/]+)$/.exec(key);
    if (reg) {
      key=reg[1]+"@"+reg[2]; // Transform @ to /
    }

    var options = formatOptions(request);

    func.call(this.store, key, options, (error, values) => {
      debug("_get", "type=", name, "key=", key, "values=", values);
      if (error) {
        // send 500
        if (error.code === 'NOT_FOUND') {
          response.status(404).send('Key not found');
          return;
        }

        response.status(500).send(String(error));
        return;
      }

      response.json(values);
    });
  }

  _getLast(request, response) {
    this._get("getLast", request, response, this.store.getLast);
  }

  _getHistory(request, response) {
    this._get("getHistory", request, response, this.store.getHistory);
  }

  _getMinMaxAvgSum(request, response) {
    this._get("getMinMaxAvgSum", request, response, this.store.getMinMaxAvgSum);
  }

  _postLast(request, response) {
    this._set("getLastSet", request, response, this.store.getLast);
  }

  _postHistory(request, response) {
    this._set("getHistorySet", request, response, this.store.getHistory);
  }

  _postMinMaxAvgSum(request, response) {
    this._set("getMinMaxAvgSumSet", request, response, this.store.getMinMaxAvgSum);
  }
}

function formatOptions(request) {
  var ret = {};

  var query = request.query;
  if (query.limit) {
    ret.limit = parseInt(query.limit, 10);
  }

  if (query.minDate) {
    ret.minDate = new Date(query.minDate);
  }

  if (query.maxDate) {
    ret.maxDate = new Date(query.maxDate);
  }

  if (query.averageMs) {
    ret.averageMs = parseInt(query.averageMs, 10);
  }

  if (query.step) {
    ret.stepMs = parseInt(query.step, 10) * 1000;
  }

  return ret;
}

module.exports = Server;
<|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    mkdirp = require('mkdirp'),
    exec = require('child_process').exec,
    express = require('express');
    base = path.join(process.cwd(), 'tests'),
    covDir = '/tmp/yui-coverage/';

var moduleName = path.basename(process.cwd());

var mods = {};
var modules = [];

var YUI;

var parseUpstream = function(options, moduleName) {
    var mods = [];
    if (options.modules) {
        mods = options.modules.replace(/ /g, '').split();
    }
    if (!mods.length) {
        mods.push(moduleName);
    }
    options.modules = [];
    var ypath = path.join(process.cwd(), '../../build/yui-nodejs/yui-nodejs.js');
    if (path.existsSync(ypath)) {
        if (!YUI) {
            YUI = require(ypath).YUI;
        }
        var Y = YUI();
        var loader = new Y.Loader({
            ignoreRegistered: true
        });
        loader.require(mods);
        var out = loader.resolve(true);
        out.jsMods.forEach(function(i) {
            options.modules.push(i.name);
            parseModuleMeta(i.name, true);
        });
    } else {
        console.error('[error]'.bold.red, 'Could not find yui-nodejs seed to parse upstream');
    }

    options.modules = options.modules.join(',');
    return options;
};

var parseModuleMeta = function(moduleName, skipMeta) {
    var meta, i, m,
        metaPath = path.join('../', moduleName, 'meta', moduleName + '.json');

    if (moduleName === 'yui') {
        mods['yui-core'] = true;
    }

    if (skipMeta) {
        mods[moduleName] = true;
    } else {
        if (path.existsSync(metaPath)) {
            meta = JSON.parse(fs.readFileSync(metaPath));
        } else {
            console.log(('Failed to find meta for' + moduleName).bold.red);
            console.log(metaPath.bold.red);
            return;
        }

        for (i in meta) {
            mods[i] = true;
            for (m in meta[i]) {
                switch (m) {
                    case 'use':
                        meta[i].use.forEach(function(k) {
                            mods[k] = true;
                        });
                        break;
                    case 'submodules':
                    case 'plugins':
                        Object.keys(meta[i][m]).forEach(function(k) {
                            mods[k] = true;
                            if (meta[i][m][k].submodules) {
                                Object.keys(meta[i][m][k].submodules).forEach(function(m) {
                                    mods[m] = true;
                                });
                            }
                        });
                        break;
                }
            }
        }
    }

    modules = Object.keys(mods).sort();
};

var app = express.createServer();
app.configure(function() {
    app.use(express.bodyParser());
});

var io = require('socket.io').listen(app);
io.set('log level', 1);

var resultSocket;

io.sockets.on('connection', function (socket) {
    resultSocket = socket;
});

app.get('/', function(req, res, next) {
    fs.readdir(base, function(err, d) {
        var files = [];
        d.forEach(function(file) {
            var ext = path.extname(file);
            if (ext.indexOf('htm') > 0) {
                files.push(file);
            }
        });
        if (files.length > 1) {
            var str = '
Choose your test file

';
            files.sort();
            files.forEach(function(f) {
                str += '
' + f + '
';
            });
            str += '
';
            res.send(str);
        } else {
            //Redirect here so the next handler get's called..
            res.redirect('/' + files[0]);
        }
    });
});

var serveCoverage = function(module, res) {

    console.log('Serving Coverage file for: '.white, module.yellow);
    var dir = path.join(covDir, module + '_' + Date.now());
    mkdirp(dir, function() {
        var modpath = path.join(process.cwd(), '../../build/', module, module + '.js');
        var covModFile = path.join(dir, module + '.js');
        var cmd = 'java -jar "' + path.join(__dirname, '../java/yuitest-coverage.jar') + '" -o "' + covModFile + '" "' + modpath + '"';
        console.log('Executing Coverage Jar against'.magenta, module.yellow);
        exec(cmd, function() {
            console.log('Coverage complete, serving..'.white, module.yellow);
            fs.readFile(covModFile, function(err, str) {
                res.contentType('.js');
                res.send(str);
            });
        });
    });
};

app.get('/dynamic/reporter.js', function(req, res) {
    res.contentType('.js');
    res.send(fs.readFileSync(path.join(__dirname, '../lib/reporter.js'), 'utf8'));
});

var lastResult;

app.post('/results', function(req, res) {
    console.log('Results Received, writing to file and converting output'.yellow);
    var dir = path.join(covDir, 'results-' + Date.now());
    lastResult = path.join(dir, 'results.json');
    mkdirp(dir, function() {
        console.log('Writing last results'.white);
        fs.writeFileSync(lastResult, req.body.results, 'utf8');
        console.log('Building Coverage Report'.magenta);
        var cmd = 'java -jar "' + path.join(__dirname, '../java/yuitest-coverage-report.jar') + '" -o "' + dir + '" "' + lastResult + '"';
        exec(cmd, function() {
            if (resultSocket) {
                resultSocket.emit('done', { });
            }
            console.log('Coverage Report Complete'.magenta);
        })
    });

    res.send('Good');
});

app.get('/results/'+'*', function(req, res) {
    var file = req.params[0];
    if (!file) {
        file = 'index.html';
    }
    console.log('Serving Results..'.white, file.yellow);

    var p = path.join(path.dirname(lastResult), file);
    if (path.existsSync(p)) {
        console.log('File Path:'.white, p.yellow);
        fs.readFile(p, 'utf8', function(err, str) {
            res.contentType('.html');
            res.send(str);
        });
    } else {
        console.log('Trying to load results with no content, redirecting to /'.magenta);
        res.redirect('/');
    }
});

app.get('/results', function(req, res) {
    res.redirect('/results/');
});

var append = '';
    append += '';

app.get('*', function(req, res) {

    var file = req.params[0];
    var ext = path.extname(file);
    var cover = false;
    var doAppend = false;

    var item = file.split('/');

    if (mods[item[2]] && ext === '.js') {
        cover = true;
        if (item[2].indexOf('selector') > -1) {
            cover = false;
        }
    }

    if (cover) {
        serveCoverage(item[2], res);
    } else {

        //Check Build
        var p = path.join(process.cwd(), '../../', file);
        //Check src
        if (!path.existsSync(p)) {
            var p = path.join(process.cwd(), '../', file);
        }
        //Check ./tests/
        if (!path.existsSync(p)) {
            if (path.extname(p).indexOf('htm') > 0) {
                doAppend = true;
            }
            var p = path.join(base, file);
        }
        if (!path.existsSync(p)) {
            res.send(404);
            //res.redirect('/');
            return;
        }
        fs.readFile(p, function(err, str) {
            res.contentType(ext);
            if (doAppend) {
                str += append;
            }
            res.send(str);
        });
    }
});

module.exports = {
    start: function(options) {
        var port = options.port;
        if (options.modules) {
            modules = options.modules.replace(/ /, '').split(',');
            mods = {};
            modules.forEach(function(module) {
                parseModuleMeta(module);
            });
        } else {
            parseModuleMeta(moduleName);
        }
        if (options.upstream) {
            options = parseUpstream(options, moduleName);
        }

        if (!modules.length || !Object.keys(mods).length) {
            console.error('No modules found to cover, bailing'.bold.red);
            process.exit(1);
        }

        console.log(('Starting server: http://127.0.0.1:' + port + '/').magenta);
        console.log('Serving coverage files for these modules: '.white, modules.join().yellow);

        app.listen(port);
    }
};

<commit_msg>If no HTML file is found and there are directories, scan them for html files too<commit_after>var fs = require('fs'),
    path = require('path'),
    mkdirp = require('mkdirp'),
    exec = require('child_process').exec,
    express = require('express');
    base = path.join(process.cwd(), 'tests'),
    covDir = '/tmp/yui-coverage/';

var moduleName = path.basename(process.cwd());

var mods = {};
var modules = [];

var YUI;

var parseUpstream = function(options, moduleName) {
    var mods = [];
    if (options.modules) {
        mods = options.modules.replace(/ /g, '').split();
    }
    if (!mods.length) {
        mods.push(moduleName);
    }
    options.modules = [];
    var ypath = path.join(process.cwd(), '../../build/yui-nodejs/yui-nodejs.js');
    if (path.existsSync(ypath)) {
        if (!YUI) {
            YUI = require(ypath).YUI;
        }
        var Y = YUI();
        var loader = new Y.Loader({
            ignoreRegistered: true
        });
        loader.require(mods);
        var out = loader.resolve(true);
        out.jsMods.forEach(function(i) {
            options.modules.push(i.name);
            parseModuleMeta(i.name, true);
        });
    } else {
        console.error('[error]'.bold.red, 'Could not find yui-nodejs seed to parse upstream');
    }

    options.modules = options.modules.join(',');
    return options;
};

var parseModuleMeta = function(moduleName, skipMeta) {
    var meta, i, m,
        metaPath = path.join('../', moduleName, 'meta', moduleName + '.json');

    if (moduleName === 'yui') {
        mods['yui-core'] = true;
    }

    if (skipMeta) {
        mods[moduleName] = true;
    } else {
        if (path.existsSync(metaPath)) {
            meta = JSON.parse(fs.readFileSync(metaPath));
        } else {
            console.log(('Failed to find meta for' + moduleName).bold.red);
            console.log(metaPath.bold.red);
            return;
        }

        for (i in meta) {
            mods[i] = true;
            for (m in meta[i]) {
                switch (m) {
                    case 'use':
                        meta[i].use.forEach(function(k) {
                            mods[k] = true;
                        });
                        break;
                    case 'submodules':
                    case 'plugins':
                        Object.keys(meta[i][m]).forEach(function(k) {
                            mods[k] = true;
                            if (meta[i][m][k].submodules) {
                                Object.keys(meta[i][m][k].submodules).forEach(function(m) {
                                    mods[m] = true;
                                });
                            }
                        });
                        break;
                }
            }
        }
    }

    modules = Object.keys(mods).sort();
};

var app = express.createServer();
app.configure(function() {
    app.use(express.bodyParser());
});

var io = require('socket.io').listen(app);
io.set('log level', 1);

var resultSocket;

io.sockets.on('connection', function (socket) {
    resultSocket = socket;
});

app.get('/', function(req, res, next) {
    fs.readdir(base, function(err, d) {
        var files = [];
        d.forEach(function(file) {
            var ext = path.extname(file);
            if (ext.indexOf('htm') > 0) {
                files.push(file);
            } else {
                var dir = path.join(base, d, file);
                var stat = fs.statSync(dir);
                if (stat.isDirectory()) {
                    var subfiles = fs.readdirSync(dir);
                    console.log(subfiles);
                    subfiles.forEach(function(f) {
                        var ext = path.extname(f);
                        if (ext.indexOf('htm') > 0) {
                            files.push(path.join(file, f));
                        }
                    });
                }
            }
        });
        if (files.length > 1) {
            var str = '
Choose your test file

';
            files.sort();
            files.forEach(function(f) {
                str += '
' + f + '
';
            });
            str += '
';
            res.send(str);
        } else {
            //Redirect here so the next handler get's called..
            res.redirect('/' + files[0]);
        }
    });
});

var serveCoverage = function(module, res) {

    console.log('Serving Coverage file for: '.white, module.yellow);
    var dir = path.join(covDir, module + '_' + Date.now());
    mkdirp(dir, function() {
        var modpath = path.join(process.cwd(), '../../build/', module, module + '.js');
        var covModFile = path.join(dir, module + '.js');
        var cmd = 'java -jar "' + path.join(__dirname, '../java/yuitest-coverage.jar') + '" -o "' + covModFile + '" "' + modpath + '"';
        console.log('Executing Coverage Jar against'.magenta, module.yellow);
        exec(cmd, function() {
            console.log('Coverage complete, serving..'.white, module.yellow);
            fs.readFile(covModFile, function(err, str) {
                res.contentType('.js');
                res.send(str);
            });
        });
    });
};

app.get('/dynamic/reporter.js', function(req, res) {
    res.contentType('.js');
    res.send(fs.readFileSync(path.join(__dirname, '../lib/reporter.js'), 'utf8'));
});

var lastResult;

app.post('/results', function(req, res) {
    console.log('Results Received, writing to file and converting output'.yellow);
    var dir = path.join(covDir, 'results-' + Date.now());
    lastResult = path.join(dir, 'results.json');
    mkdirp(dir, function() {
        console.log('Writing last results'.white);
        fs.writeFileSync(lastResult, req.body.results, 'utf8');
        console.log('Building Coverage Report'.magenta);
        var cmd = 'java -jar "' + path.join(__dirname, '../java/yuitest-coverage-report.jar') + '" -o "' + dir + '" "' + lastResult + '"';
        exec(cmd, function() {
            if (resultSocket) {
                resultSocket.emit('done', { });
            }
            console.log('Coverage Report Complete'.magenta);
        })
    });

    res.send('Good');
});

app.get('/results/'+'*', function(req, res) {
    var file = req.params[0];
    if (!file) {
        file = 'index.html';
    }
    console.log('Serving Results..'.white, file.yellow);

    var p = path.join(path.dirname(lastResult), file);
    if (path.existsSync(p)) {
        console.log('File Path:'.white, p.yellow);
        fs.readFile(p, 'utf8', function(err, str) {
            res.contentType('.html');
            res.send(str);
        });
    } else {
        console.log('Trying to load results with no content, redirecting to /'.magenta);
        res.redirect('/');
    }
});

app.get('/results', function(req, res) {
    res.redirect('/results/');
});

var append = '';
    append += '';

app.get('*', function(req, res) {

    var file = req.params[0];
    var ext = path.extname(file);
    var cover = false;
    var doAppend = false;

    var item = file.split('/');

    if (mods[item[2]] && ext === '.js') {
        cover = true;
        if (item[2].indexOf('selector') > -1) {
            cover = false;
        }
    }

    if (cover) {
        serveCoverage(item[2], res);
    } else {

        //Check Build
        var p = path.join(process.cwd(), '../../', file);
        //Check src
        if (!path.existsSync(p)) {
            var p = path.join(process.cwd(), '../', file);
        }
        //Check ./tests/
        if (!path.existsSync(p)) {
            if (path.extname(p).indexOf('htm') > 0) {
                doAppend = true;
            }
            var p = path.join(base, file);
        }
        if (!path.existsSync(p)) {
            res.send(404);
            //res.redirect('/');
            return;
        }
        fs.readFile(p, function(err, str) {
            res.contentType(ext);
            if (doAppend) {
                str += append;
            }
            res.send(str);
        });
    }
});

module.exports = {
    start: function(options) {
        var port = options.port;
        if (options.modules) {
            modules = options.modules.replace(/ /, '').split(',');
            mods = {};
            modules.forEach(function(module) {
                parseModuleMeta(module);
            });
        } else {
            parseModuleMeta(moduleName);
        }
        if (options.upstream) {
            options = parseUpstream(options, moduleName);
        }

        if (!modules.length || !Object.keys(mods).length) {
            console.error('No modules found to cover, bailing'.bold.red);
            process.exit(1);
        }

        console.log(('Starting server: http://127.0.0.1:' + port + '/').magenta);
        console.log('Serving coverage files for these modules: '.white, modules.join().yellow);

        app.listen(port);
    }
};

<|endoftext|>


<commit_before>if (typeof ot === 'undefined') {
  var ot = {};
}

ot.Server = (function (global) {

  // Constructor. Takes the current document as a string and optionally the array
  // of all operations.
  function Server (document, operations) {
    this.document = document;
    this.operations = operations || [];
  }

  // Transforms a single operation against an array of operations.
  function transformAgainstAll (operation, operations) {
    // Left fold.
    var reduce = Array.prototype.reduce || function (fn, val) {
      var arr = this;
      for (var i = 0, l = arr.length; i < l; i++) {
        val = fn(val, arr[i]);
      }
      return val;
    };

    var transform = operation.constructor.transform;
    return reduce.call(operations, function (newOperation, oldOperation) {
      return transform(newOperation, oldOperation)[0];
    }, operation);
  }

  // Call this method whenever you receive an operation from a client.
  Server.prototype.receiveOperation = function (revision, operation) {
    if (revision < 0 || this.operations.length < revision) {
      throw new Error("operation revision not in history");
    }
    // Find all operations that the client didn't know of when it sent the
    // operation ...
    var concurrentOperations = this.operations.slice(revision);
    // ... and transform the operation against all these operations ...
    var transformedOperation = transformAgainstAll(operation, concurrentOperations);
    // ... and apply that on the document.
    this.document = transformedOperation.apply(this.document);
    // Store operation in history.
    this.operations.push(transformedOperation);
    // Send it to all connected clients.
    this.broadcast(transformedOperation);
  };

  // Override this method.
  Server.prototype.broadcast = function (operation) {
    throw new Error("broadcast must be defined in child class");
  };

  return Server;

})(this);

if (typeof module === 'object') {
  module.exports = ot.Server;
}<commit_msg>Simplify server code<commit_after>if (typeof ot === 'undefined') {
  var ot = {};
}

ot.Server = (function (global) {

  // Constructor. Takes the current document as a string and optionally the array
  // of all operations.
  function Server (document, operations) {
    this.document = document;
    this.operations = operations || [];
  }

  // Call this method whenever you receive an operation from a client.
  Server.prototype.receiveOperation = function (revision, operation) {
    if (revision < 0 || this.operations.length < revision) {
      throw new Error("operation revision not in history");
    }
    // Find all operations that the client didn't know of when it sent the
    // operation ...
    var concurrentOperations = this.operations.slice(revision);

    // ... and transform the operation against all these operations ...
    var transform = operation.constructor.transform;
    for (var i = 0; i < concurrentOperations.length; i++) {
      operation = transform(operation, concurrentOperations[i])[0];
    }

    // ... and apply that on the document.
    this.document = operation.apply(this.document);
    // Store operation in history.
    this.operations.push(operation);
    // Send it to all connected clients.
    this.broadcast(operation);
  };

  // Override this method.
  Server.prototype.broadcast = function (operation) {
    throw new Error("broadcast must be defined in child class");
  };

  return Server;

})(this);

if (typeof module === 'object') {
  module.exports = ot.Server;
}<|endoftext|>


<commit_before>// Browser check variables
// If you support IE, our recommendation is that you sign-in using Redirect APIs
// If you as a developer are testing using Edge InPrivate mode, please add "isEdge" to the if check
const ua = window.navigator.userAgent;
const msie = ua.indexOf("MSIE ");
const msie11 = ua.indexOf("Trident/");
const msedge = ua.indexOf("Edge/");
const isIE = msie > 0 || msie11 > 0;
const isEdge = msedge > 0;

let signInType;

// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication(msalConfig);

// Register Callbacks for Redirect flow
myMSALObj.handleRedirectCallback(authRedirectCallBack);

function authRedirectCallBack(error, response) {
    if (error) {
        console.log(error);
    } else {
        if (myMSALObj.getAccount()) {
            console.log('id_token acquired at: ' + new Date().toString());
            showWelcomeMessage(myMSALObj.getAccount());
            getTokenRedirect(loginRequest);
        } else if (response.tokenType === "Bearer") {
            console.log('access_token acquired at: ' + new Date().toString());
        } else {
            console.log("token type is:" + response.tokenType);
        }
    }
}

// Redirect: once login is successful and redirects with tokens, call Graph API
if (myMSALObj.getAccount()) {
    // avoid duplicate code execution on page load in case of iframe and Popup window.
    showWelcomeMessage(myMSALObj.getAccount());
} else {
    myMSALObj.ssoSilent(silentRequest).then((tokenResponse) => {
        if (myMSALObj.getAccount()) {
            console.log('id_token acquired at: ' + new Date().toString());
            showWelcomeMessage(myMSALObj.getAccount());
            getTokenRedirect(loginRequest);
        } else if (tokenResponse.tokenType === "Bearer") {
            console.log('access_token acquired at: ' + new Date().toString());
        } else {
            console.log("token type is:" + response.tokenType);
        }
    }).catch(error => {
        console.error("Silent Error: " + error);
        if (msal.InteractionRequiredAuthError.isInteractionRequiredError(error.errorCode, error.errorDesc)) {
            signIn("loginPopup");
        }
    });
}

async function signIn(method) {
    signInType = isIE ? "loginRedirect" : method;
    if (signInType === "loginPopup") {
        const loginResponse = await myMSALObj.loginPopup(loginRequest).catch(function (error) {
            console.log(error);
        });
        console.log(loginResponse);
        if (myMSALObj.getAccount()) {
            showWelcomeMessage(myMSALObj.getAccount());
        }
    } else if (signInType === "loginRedirect") {
        myMSALObj.loginRedirect(loginRequest)
    }
}

function signOut() {
    myMSALObj.logout();
}

async function getTokenPopup(request) {
    return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
        console.log("silent token acquisition fails.");
        if (error instanceof msal.InteractionRequiredAuthError) {
            if (msal.InteractionRequiredAuthError.isInteractionRequiredError(error.errorCode, error.errorDesc)) {
                // fallback to interaction when silent call fails
                console.log("acquiring token using popup");
                return myMSALObj.acquireTokenPopup(request).catch(error => {
                    console.error(error);
                });
            }
        } else {
            console.error(error);
        }
    });
}

// This function can be removed if you do not need to support IE
async function getTokenRedirect(request) {
    return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
        console.log("silent token acquisition fails.");
        if (error instanceof AuthenticationRequiredError) {
            if (AuthenticationRequiredError.isInteractionRequiredError(error.errorCode, error.errorDesc)) {
                // fallback to interaction when silent call fails
                console.log("acquiring token using redirect");
                myMSALObj.acquireTokenRedirect(request);
            }
        } else {
            console.error(error);
        }
    });
}
<commit_msg>Update sample<commit_after>// Browser check variables
// If you support IE, our recommendation is that you sign-in using Redirect APIs
// If you as a developer are testing using Edge InPrivate mode, please add "isEdge" to the if check
const ua = window.navigator.userAgent;
const msie = ua.indexOf("MSIE ");
const msie11 = ua.indexOf("Trident/");
const msedge = ua.indexOf("Edge/");
const isIE = msie > 0 || msie11 > 0;
const isEdge = msedge > 0;

let signInType;

// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication(msalConfig);

// Register Callbacks for Redirect flow
myMSALObj.handleRedirectCallback(authRedirectCallBack);

function authRedirectCallBack(error, response) {
    if (error) {
        console.log(error);
    } else {
        if (myMSALObj.getAccount()) {
            console.log('id_token acquired at: ' + new Date().toString());
            showWelcomeMessage(myMSALObj.getAccount());
            getTokenRedirect(loginRequest);
        } else if (response.tokenType === "Bearer") {
            console.log('access_token acquired at: ' + new Date().toString());
        } else {
            console.log("token type is:" + response.tokenType);
        }
    }
}

// Redirect: once login is successful and redirects with tokens, call Graph API
if (myMSALObj.getAccount()) {
    // avoid duplicate code execution on page load in case of iframe and Popup window.
    showWelcomeMessage(myMSALObj.getAccount());
} else {
    myMSALObj.ssoSilent(silentRequest).then((tokenResponse) => {
        if (myMSALObj.getAccount()) {
            console.log('id_token acquired at: ' + new Date().toString());
            showWelcomeMessage(myMSALObj.getAccount());
            getTokenRedirect(loginRequest);
        } else if (tokenResponse.tokenType === "Bearer") {
            console.log('access_token acquired at: ' + new Date().toString());
        } else {
            console.log("token type is:" + response.tokenType);
        }
    }).catch(error => {
        console.error("Silent Error: " + error);
        if (error instanceof msal.InteractionRequiredAuthError) {
            signIn("loginPopup");
        }
    });
}

async function signIn(method) {
    signInType = isIE ? "loginRedirect" : method;
    if (signInType === "loginPopup") {
        const loginResponse = await myMSALObj.loginPopup(loginRequest).catch(function (error) {
            console.log(error);
        });
        console.log(loginResponse);
        if (myMSALObj.getAccount()) {
            showWelcomeMessage(myMSALObj.getAccount());
        }
    } else if (signInType === "loginRedirect") {
        myMSALObj.loginRedirect(loginRequest)
    }
}

function signOut() {
    myMSALObj.logout();
}

async function getTokenPopup(request) {
    return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
        console.log("silent token acquisition fails.");
        if (error instanceof msal.InteractionRequiredAuthError) {
            // fallback to interaction when silent call fails
            console.log("acquiring token using popup");
            return myMSALObj.acquireTokenPopup(request).catch(error => {
                console.error(error);
            });
        } else {
            console.error(error);
        }
    });
}

// This function can be removed if you do not need to support IE
async function getTokenRedirect(request) {
    return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
        console.log("silent token acquisition fails.");
        if (error instanceof msal.InteractionRequiredAuthError) {
            // fallback to interaction when silent call fails
            console.log("acquiring token using redirect");
            myMSALObj.acquireTokenRedirect(request);
        } else {
            console.error(error);
        }
    });
}
<|endoftext|>


<commit_before>/*
Script: ART.Widget.js

License:
	MIT-style license.

Requires:
	@require 'jsspec'
	@require '../Assets/Scripts/mootools.js'
	@require '../../Source/Base/ART.js'
	@require '../../Source/Base/ART.Widget.js'
*/

var w;
var container;

describe('ART.Widget', {

	before_all : function(){
		container = new Element('div')
			.inject(document.body)
			.setStyles({
				position:'absolute'
				,bottom:'0px'
				,right:'0px'
				,zIndex:'9999'
				,backgroundColor:'#fff'
			})
		;
	}
	,before : function(){
		w = new ART.Widget();
	}
	,after : function(){
		container.empty();
		$(w).dispose();
		w = null;
	}

	,'should exist': function(){
		value_of(ART.Widget).should_not_be_undefined();
	}

	,'should implement toElement': function(){
		$(w).inject(container);
		value_of( container.contains($(w)) ).should_be_true();
	}

});
<commit_msg>more basic Widget specs<commit_after>/*
Script: ART.Widget.js

License:
	MIT-style license.

Requires:
	@require 'jsspec'
	@require '../Assets/Scripts/mootools.js'
	@require '../../Source/Base/ART.js'
	@require '../../Source/Base/ART.Widget.js'
*/

var w;
var container;

describe('ART.Widget', {

	before_all : function(){
		container = new Element('div')
			.inject(document.body)
			.setStyles({
				position:'absolute'
				,bottom:'0px'
				,right:'0px'
				,zIndex:'9999'
				,backgroundColor:'#fff'
			})
		;
	}
	,before : function(){
		w = new ART.Widget();
	}
	,after : function(){
		container.empty();
		$(w).dispose();
		w = null;
	}

	,'should exist': function(){
		value_of(ART.Widget).should_not_be_undefined();
	}

	,'should implement toElement': function(){
		$(w).inject(container);
		value_of( container.contains($(w)) ).should_be_true();
	}

	,'should get ART.Sheet Selector': function(){
		ART.Widget.SubClass = new Class({
			Extends: ART.Widget,
			ns: 'mynamespace',
			name: 'mywidgetsubclass'
		});

		w = new ART.Widget.SubClass();
		value_of( w.getSelector() ).should_be( 'mywidgetsubclass' );
	}

	,'should set classname of root node': function(){
		ART.Widget.SubClass = new Class({
			Extends: ART.Widget,
			ns: 'mynamespace',
			name: 'mywidgetsubclass'
		});

		w = new ART.Widget.SubClass();
		value_of( $(w).hasClass('mynamespace') ).should_be_true();
		value_of( $(w).hasClass('mynamespace-mywidgetsubclass') ).should_be_true();
	}

});
<|endoftext|>


<commit_before>'use strict';

var remove   = require('es5-ext/lib/Array/prototype/remove')
  , d        = require('es5-ext/lib/Object/descriptor')
  , callable = require('es5-ext/lib/Object/valid-callable')
  , ee       = require('event-emitter/lib/core')
  , nextTick = require('next-tick')
  , now      = require('time-uuid/lib/time')
  , proto    = require('./_proto')
  , Event    = require('./event')
  , objects  = require('./objects')
  , history  = require('./history')

  , call = Function.prototype.call
  , getObject = objects._get
  , out = exports, stamp = null, reverse = {}
  , clear = function () { stamp = null; }
  , byStamp = function (a, b) { return b.stamp - a.stamp; }
  , relType = { relation: true, 'relation-set-item': true }
  , objectType = { object: true, namespace: true, prototype: true };

Object.defineProperties(ee(out), {
	_id: d('0'),
	_add: d(function (event, noEvents) {
		var obj, id, previous, objHistory, dismissed, assigned, addedTo
		  , removedFrom;

		obj = event.obj;
		id = obj._id_;

		// Update history and reverse relations index
		objHistory = history.hasOwnProperty(id) && history[id];
		if (!objHistory) {
			history[id] = [event];
		} else {
			previous = objHistory[0];
			if (previous) {
				if (previous.stamp > event.stamp) {
					// Outdated update, add to history and quit
					objHistory.unshift(event);
					objHistory.sort(byStamp);
					return;
				} else if (previous.stamp < event.stamp) {
					objHistory.unshift(event);
				} else {
					if ((previous.sourceId === event.sourceId) &&
							(previous.value === event.value)) {
						obj.$$setValue(event.value);
						return;
					}
					objHistory.splice(0, 1, event);
					if (previous.value === event.value) {
						obj.$$setValue(event.value);
						if (noEvents) return;
						out.emit('update', event, previous);
						return;
					}
				}
				if (previous.value && (previous.value !== event.value)) {
					if (obj._type_ === 'relation-set-item') {
						if (obj._key_[0] === '7') {
							id = obj._key_.slice(1);
							dismissed = getObject(id);
							if (dismissed._type_ === 'object') remove.call(reverse[id], obj);
							else dismissed = null;
						}
					}
					if (previous.value._type_) {
						if (obj._type_ === 'relation') {
							if (previous.value._type_ === 'object') {
								id = previous.value._id_;
								remove.call(reverse[id], obj);
								dismissed = previous.value;
							}
						} else if (objectType[previous.value._type_]) {
							removedFrom = previous.value;
						}
					}
				}
			} else {
				objHistory.unshift(event);
			}
		}
		if (event.value && (!previous || (previous.value !== event.value))) {
			if (obj._type_ === 'relation-set-item') {
				if (obj._key_[0] === '7') {
					id = obj._key_.slice(1);
					assigned = getObject(id);
					if (assigned._type_ === 'object') {
						if (reverse.hasOwnProperty(id)) reverse[id].push(obj);
						else reverse[id] = [obj];
					} else {
						assigned = null;
					}
				}
			}
			if (event.value._type_) {
				if (obj._type_ === 'relation') {
					if (event.value._type_ === 'object') {
						id = event.value._id_;
						if (reverse.hasOwnProperty(id)) reverse[id].push(obj);
						else reverse[id] = [obj];
						assigned = event.value;
					}
				} else if (objectType[event.value._type_]) {
					addedTo = event.value;
				}
			}
		}

		obj.$$setValue(event.value);
		if (noEvents) return;
		if (relType[obj._type_]) {
			do {
				obj = obj.obj;
				if (!obj) break;
			} while (relType[obj._type_]);
			if (obj) obj.emit('update', event, previous);
			if (dismissed) dismissed.emit('dismiss', event, previous);
			if (assigned) assigned.emit('assign', event, previous);
		} else if (removedFrom || addedTo) {
			obj.emit('selfupdate', event, previous);
			if (removedFrom) removedFrom.emit('remove', event, previous);
			if (addedTo) addedTo.emit('add', event, previous);
		}
		out.emit('update', event, previous);
	}),
	_remove: d(function (id, noEvents) {
		var obj = getObject(id)
		  , objHistory = history.hasOwnProperty(id) && history[id]
		  , lastEvent = objHistory[0], dismissed, removedFrom;

		if (lastEvent && lastEvent.value) {
			if (obj._type_ === 'relation-set-item') {
				if (obj._key_[0] === '7') {
					id = obj._key_.slice(1);
					dismissed = getObject(id);
					if (dismissed._type_ === 'object') remove.call(reverse[id], obj);
					else dismissed = null;
				}
			}
			if (lastEvent.value._type_) {
				if (obj._type_ === 'relation') {
					if (lastEvent.value._type_ === 'object') {
						id = lastEvent.value._id_;
						remove.call(reverse[id], obj);
						dismissed = lastEvent.value;
					}
				} else if (objectType[lastEvent.value._type_]) {
					removedFrom = lastEvent.value;
				}
			}
		}

		delete history[id];
		obj.$$setValue();
		if (noEvents) return;
		if (relType[obj._type_]) {
			do {
				obj = obj.obj;
				if (!obj) break;
			} while (relType[obj._type_]);
			if (obj && lastEvent) obj.emit('update', null, lastEvent);
			if (dismissed) dismissed.emit('dismiss', null, lastEvent);
		} else if (removedFrom) {
			obj.emit('selfupdate', null, lastEvent);
			removedFrom.emit('remove', null, lastEvent);
		}
		out.emit('remove', id);
	})
});

Object.defineProperties(proto, {
	_signal_: d(function (value) {
		if (stamp == null) {
			stamp = now();
			nextTick(clear);
		}
		out._add(new Event(this, value, stamp));
	}),
	_forEachReverse_: d(function (cb/*, thisArg*/) {
		var data, thisArg = arguments[1];
		callable(cb);
		data = reverse.hasOwnProperty(this._id_) && reverse[this._id_];
		if (!data) return;
		data.forEach(function (rel) {
			call.call(cb, thisArg, rel, rel._id_, this);
		}, this);
	})
});
<commit_msg>Emit 'selfupdate' event on every object<commit_after>'use strict';

var remove   = require('es5-ext/lib/Array/prototype/remove')
  , d        = require('es5-ext/lib/Object/descriptor')
  , callable = require('es5-ext/lib/Object/valid-callable')
  , ee       = require('event-emitter/lib/core')
  , nextTick = require('next-tick')
  , now      = require('time-uuid/lib/time')
  , proto    = require('./_proto')
  , Event    = require('./event')
  , objects  = require('./objects')
  , history  = require('./history')

  , call = Function.prototype.call
  , getObject = objects._get
  , out = exports, stamp = null, reverse = {}
  , clear = function () { stamp = null; }
  , byStamp = function (a, b) { return b.stamp - a.stamp; }
  , relType = { relation: true, 'relation-set-item': true }
  , objectType = { object: true, namespace: true, prototype: true };

Object.defineProperties(ee(out), {
	_id: d('0'),
	_add: d(function (event, noEvents) {
		var obj, id, previous, objHistory, dismissed, assigned, addedTo
		  , removedFrom, masterObj;

		obj = event.obj;
		id = obj._id_;

		// Update history and reverse relations index
		objHistory = history.hasOwnProperty(id) && history[id];
		if (!objHistory) {
			history[id] = [event];
		} else {
			previous = objHistory[0];
			if (previous) {
				if (previous.stamp > event.stamp) {
					// Outdated update, add to history and quit
					objHistory.unshift(event);
					objHistory.sort(byStamp);
					return;
				} else if (previous.stamp < event.stamp) {
					objHistory.unshift(event);
				} else {
					if ((previous.sourceId === event.sourceId) &&
							(previous.value === event.value)) {
						obj.$$setValue(event.value);
						return;
					}
					objHistory.splice(0, 1, event);
					if (previous.value === event.value) {
						obj.$$setValue(event.value);
						if (noEvents) return;
						out.emit('update', event, previous);
						return;
					}
				}
				if (previous.value && (previous.value !== event.value)) {
					if (obj._type_ === 'relation-set-item') {
						if (obj._key_[0] === '7') {
							id = obj._key_.slice(1);
							dismissed = getObject(id);
							if (dismissed._type_ === 'object') remove.call(reverse[id], obj);
							else dismissed = null;
						}
					}
					if (previous.value._type_) {
						if (obj._type_ === 'relation') {
							if (previous.value._type_ === 'object') {
								id = previous.value._id_;
								remove.call(reverse[id], obj);
								dismissed = previous.value;
							}
						} else if (objectType[previous.value._type_]) {
							removedFrom = previous.value;
						}
					}
				}
			} else {
				objHistory.unshift(event);
			}
		}
		if (event.value && (!previous || (previous.value !== event.value))) {
			if (obj._type_ === 'relation-set-item') {
				if (obj._key_[0] === '7') {
					id = obj._key_.slice(1);
					assigned = getObject(id);
					if (assigned._type_ === 'object') {
						if (reverse.hasOwnProperty(id)) reverse[id].push(obj);
						else reverse[id] = [obj];
					} else {
						assigned = null;
					}
				}
			}
			if (event.value._type_) {
				if (obj._type_ === 'relation') {
					if (event.value._type_ === 'object') {
						id = event.value._id_;
						if (reverse.hasOwnProperty(id)) reverse[id].push(obj);
						else reverse[id] = [obj];
						assigned = event.value;
					}
				} else if (objectType[event.value._type_]) {
					addedTo = event.value;
				}
			}
		}

		obj.$$setValue(event.value);
		if (noEvents) return;
		obj.emit('selfupdate', event, previous);
		if (relType[obj._type_]) {
			masterObj = obj.obj;
			while (masterObj && relType[masterObj._type_]) masterObj = masterObj.obj;
			if (masterObj) masterObj.emit('update', event, previous);
			if (dismissed) dismissed.emit('dismiss', event, previous);
			if (assigned) assigned.emit('assign', event, previous);
		} else if (removedFrom || addedTo) {
			if (removedFrom) removedFrom.emit('remove', event, previous);
			if (addedTo) addedTo.emit('add', event, previous);
		}
		out.emit('update', event, previous);
	}),
	_remove: d(function (id, noEvents) {
		var obj = getObject(id)
		  , objHistory = history.hasOwnProperty(id) && history[id]
		  , lastEvent = objHistory[0], dismissed, removedFrom;

		if (lastEvent && lastEvent.value) {
			if (obj._type_ === 'relation-set-item') {
				if (obj._key_[0] === '7') {
					id = obj._key_.slice(1);
					dismissed = getObject(id);
					if (dismissed._type_ === 'object') remove.call(reverse[id], obj);
					else dismissed = null;
				}
			}
			if (lastEvent.value._type_) {
				if (obj._type_ === 'relation') {
					if (lastEvent.value._type_ === 'object') {
						id = lastEvent.value._id_;
						remove.call(reverse[id], obj);
						dismissed = lastEvent.value;
					}
				} else if (objectType[lastEvent.value._type_]) {
					removedFrom = lastEvent.value;
				}
			}
		}

		delete history[id];
		obj.$$setValue();
		if (noEvents) return;
		if (relType[obj._type_]) {
			do {
				obj = obj.obj;
				if (!obj) break;
			} while (relType[obj._type_]);
			if (obj && lastEvent) obj.emit('update', null, lastEvent);
			if (dismissed) dismissed.emit('dismiss', null, lastEvent);
		} else if (removedFrom) {
			obj.emit('selfupdate', null, lastEvent);
			removedFrom.emit('remove', null, lastEvent);
		}
		out.emit('remove', id);
	})
});

Object.defineProperties(proto, {
	_signal_: d(function (value) {
		if (stamp == null) {
			stamp = now();
			nextTick(clear);
		}
		out._add(new Event(this, value, stamp));
	}),
	_forEachReverse_: d(function (cb/*, thisArg*/) {
		var data, thisArg = arguments[1];
		callable(cb);
		data = reverse.hasOwnProperty(this._id_) && reverse[this._id_];
		if (!data) return;
		data.forEach(function (rel) {
			call.call(cb, thisArg, rel, rel._id_, this);
		}, this);
	})
});
<|endoftext|>


<commit_before>"use strict";

/**

 * Module dependencies

 */

var socketio = require('socket.io');
var messagingService  = require('../services/messagingService');
var channelService  = require('../services/channelService');
var projectService  = require('../services/projectService');
var models  = require('../models');
var socketioJwt = require('socketio-jwt');

var redis = require('socket.io-redis');
var outside_io = require("socket.io-emitter")({ host: '127.0.0.1', port: 6379 });

module.exports.listen = function(app){

    var io = socketio.listen(app);

    io.adapter(redis({ host: 'localhost', port: 6379 }));

    var message_socket = io.of('/messages');

    var notification_socket = io.of('/notification');

    var connected_clients = {};

    notification_socket.use(socketioJwt.authorize({
      secret: 'mySecretPassword',
      handshake: true
    }));

    message_socket.use(socketioJwt.authorize({
      secret: 'mySecretPassword',
      handshake: true
    }));

    //namespace to handle notifications
    notification_socket.on('connection', function(socket){

      socket.join('SELF_' + socket.decoded_token._id);

      socket.on('join-room', function(data){
        socket.join(data.room);

        messagingService.getProjectChannelsUpdates(data.projectId, data.userId, function(updates){
            socket.emit('channels-updates', updates);
        });

        //To this new online, send all the previously existent ones
        if(connected_clients[data.room] !== undefined){
          var x;
          for(x in connected_clients[data.room]){
            socket.emit("online-users", {type:"add", id: connected_clients[data.room][x].id});
          }
        }

        addToOnlineUsers(data.room, socket.decoded_token, function(){
          //Emit online user to all users in room
          notification_socket.to(data.room).emit("online-users", {type:"add", id: socket.decoded_token._id});
        });
      });

      //on ping save last activity date
      socket.on("ping", function(data) {
          messagingService.storeDisconnectionDate(data);
          console.log("pong");
      });

      //on typing, broadcast everyone but typer
      socket.on("typing", function(data) {
          socket.broadcast.emit("typing", {typing: data.typing, msg: data.who + ' is typing..'});
      });

      socket.on('leave-room', function(data){
        socket.leave(data.room);
        removeFromOnlineUsers(data.room, socket.decoded_token, function(){
          //Emit online user to all users in room
          notification_socket.to(data.room).emit("online-users", {type:"remove", id: socket.decoded_token._id});
        });
      });

      socket.on('system', function(data){
        console.log('data: ', data);
        /*
          data={
            projectId: projectId,
            userId: userId,
            content: content,

              }
        */

        projectService.getProjectMembers(data.projectId, function(member_ids){
            if(member_ids !== null && member_ids !== undefined){
              var memberId;
              for(memberId in member_ids){
                  socket.to('SELF_' + memberId).emit("system", { data : data });
                  console.log("emiti al id: ", memberId);
              }
            }
        });
      });
    });

    //namespace to handle channel rooms and messages
    message_socket.on('connection', function(socket){
      socket.on('join-room', function(data){
        socket.join(data.room);
      });

      //on chat message, broadcast to everyone but sender
      socket.on('message', function(data){
        if(data.message.message.text.length <= models.Message.contentLength()){
          socket.broadcast.to(data.room).emit('message', data.message);
          if(isNaN(data.room)){
            //Direct channel
            notification_socket.to('SELF_' + data.message.message.destinationUser).emit("transient-notification", {type:"direct", id: data.message.message.user});
          } else {
            if(data.channel_type === 'P'){
              //Group and private channel

              //send notifications to each active member of the groupal private channel
              channelService.getChannelActiveMembers(data.room, function(members){
                  var x;
                  for(x in members){
                    notification_socket.to('SELF_' + members[x]).emit("transient-notification", {type:"private-channel", id: data.room});
                  }
              });
            } else {
              //Group and shared channel
              notification_socket.to(data.project_room).emit("transient-notification", {type:"channel", id: data.room});
            }
          }
          messagingService.storeMessage(data);
        } else {
          socket.emit('message-error', "message too long.");
        }
      });

      socket.on('leave-room', function(data){
        socket.leave(data.room);
      });

      socket.on('disconnect', function(){
      });
    });

    // Given a socket token, stores it at a room structure to keep track of online users.
    function addToOnlineUsers(room, decoded_token, callback){
      if(connected_clients[room] === undefined){
        connected_clients[room] = [];
      }

      //delete if existed
      connected_clients[room] = connected_clients[room]
             .filter(function (el) {
                      return el.id !== decoded_token._id;
                     });

      //add again
      connected_clients[room].push({id: decoded_token._id});
      callback();
    }

    function removeFromOnlineUsers(room, decoded_token, callback){
      if(connected_clients[room] !== undefined){

        connected_clients[room] = connected_clients[room]
               .filter(function (el) {
                        return el.id !== decoded_token._id;
                       });
      }

      callback();
    }

    /*notification_socket.on('connection', function(socket){
      //on connection broadcast message to other connected users
      socket.broadcast.emit('connection', {connected: true, user: socket.handshake.query.user, namespace: schoolSocket.name +' namespace'});

      //add user to online users
      online_users_school.push(socket.handshake.query.user);

      socket.on('ready', function() {
          online_users_school.forEach(function(user, index) {
          socket.emit('connection', {connected: true, user: user, namespace: schoolSocket.name +' namespace'});
        });
      });

      //on disconnect event broadcast message to other connected users
      socket.on('disconnect', function(){
        //remove user from online users
        socket.broadcast.emit('connection', {connected: false, user: socket.handshake.query.user});
        online_users_school.splice(online_users_school.indexOf(socket.handshake.query.user), 1);
      });
    });*/

    return io;
};

module.exports.systemEmit = function(projectId, data){

  projectService.getProjectMembers(projectId, function(member_ids){
      if(member_ids !== null && member_ids !== undefined){
        /*
          data={
            projectId: projectId,
            userId: userId,
            content: content,

              }
        */
        var x;
        for(x in member_ids){
            outside_io.of('/notification').to('SELF_' + member_ids[x].id).emit("system", { data : data });
        }
      }
  });

};
<commit_msg>se agrega projectId a payload de transient-notifications<commit_after>"use strict";

/**

 * Module dependencies

 */

var socketio = require('socket.io');
var messagingService  = require('../services/messagingService');
var channelService  = require('../services/channelService');
var projectService  = require('../services/projectService');
var models  = require('../models');
var socketioJwt = require('socketio-jwt');

var redis = require('socket.io-redis');
var outside_io = require("socket.io-emitter")({ host: '127.0.0.1', port: 6379 });

module.exports.listen = function(app){

    var io = socketio.listen(app);

    io.adapter(redis({ host: 'localhost', port: 6379 }));

    var message_socket = io.of('/messages');

    var notification_socket = io.of('/notification');

    var connected_clients = {};

    notification_socket.use(socketioJwt.authorize({
      secret: 'mySecretPassword',
      handshake: true
    }));

    message_socket.use(socketioJwt.authorize({
      secret: 'mySecretPassword',
      handshake: true
    }));

    //namespace to handle notifications
    notification_socket.on('connection', function(socket){

      socket.join('SELF_' + socket.decoded_token._id);

      socket.on('join-room', function(data){
        socket.join(data.room);

        messagingService.getProjectChannelsUpdates(data.projectId, data.userId, function(updates){
            socket.emit('channels-updates', updates);
        });

        //To this new online, send all the previously existent ones
        if(connected_clients[data.room] !== undefined){
          var x;
          for(x in connected_clients[data.room]){
            socket.emit("online-users", {type:"add", id: connected_clients[data.room][x].id});
          }
        }

        addToOnlineUsers(data.room, socket.decoded_token, function(){
          //Emit online user to all users in room
          notification_socket.to(data.room).emit("online-users", {type:"add", id: socket.decoded_token._id});
        });
      });

      //on ping save last activity date
      socket.on("ping", function(data) {
          messagingService.storeDisconnectionDate(data);
          console.log("pong");
      });

      //on typing, broadcast everyone but typer
      socket.on("typing", function(data) {
          socket.broadcast.emit("typing", {typing: data.typing, msg: data.who + ' is typing..'});
      });

      socket.on('leave-room', function(data){
        socket.leave(data.room);
        removeFromOnlineUsers(data.room, socket.decoded_token, function(){
          //Emit online user to all users in room
          notification_socket.to(data.room).emit("online-users", {type:"remove", id: socket.decoded_token._id});
        });
      });

      socket.on('system', function(data){
        console.log('data: ', data);
        /*
          data={
            projectId: projectId,
            userId: userId,
            content: content,

              }
        */

        projectService.getProjectMembers(data.projectId, function(member_ids){
            if(member_ids !== null && member_ids !== undefined){
              var memberId;
              for(memberId in member_ids){
                  socket.to('SELF_' + memberId).emit("system", { data : data });
                  console.log("emiti al id: ", memberId);
              }
            }
        });
      });
    });

    //namespace to handle channel rooms and messages
    message_socket.on('connection', function(socket){
      socket.on('join-room', function(data){
        socket.join(data.room);
      });

      //on chat message, broadcast to everyone but sender
      socket.on('message', function(data){
        if(data.message.message.text.length <= models.Message.contentLength()){
          socket.broadcast.to(data.room).emit('message', data.message);
          if(isNaN(data.room)){
            //Direct channel
            notification_socket.to('SELF_' + data.message.message.destinationUser).emit("transient-notification", {type:"direct", id: data.message.message.user, projectId: data.message.message.projectId});
          } else {
            if(data.channel_type === 'P'){
              //Group and private channel

              //send notifications to each active member of the groupal private channel
              channelService.getChannelActiveMembers(data.room, function(members){
                  var x;
                  for(x in members){
                    notification_socket.to('SELF_' + members[x]).emit("transient-notification", {type:"private-channel", id: data.room, projectId: data.message.message.projectId});
                  }
              });
            } else {
              //Group and shared channel
              notification_socket.to(data.project_room).emit("transient-notification", {type:"channel", id: data.room});
            }
          }
          messagingService.storeMessage(data);
        } else {
          socket.emit('message-error', "message too long.");
        }
      });

      socket.on('leave-room', function(data){
        socket.leave(data.room);
      });

      socket.on('disconnect', function(){
      });
    });

    // Given a socket token, stores it at a room structure to keep track of online users.
    function addToOnlineUsers(room, decoded_token, callback){
      if(connected_clients[room] === undefined){
        connected_clients[room] = [];
      }

      //delete if existed
      connected_clients[room] = connected_clients[room]
             .filter(function (el) {
                      return el.id !== decoded_token._id;
                     });

      //add again
      connected_clients[room].push({id: decoded_token._id});
      callback();
    }

    function removeFromOnlineUsers(room, decoded_token, callback){
      if(connected_clients[room] !== undefined){

        connected_clients[room] = connected_clients[room]
               .filter(function (el) {
                        return el.id !== decoded_token._id;
                       });
      }

      callback();
    }

    /*notification_socket.on('connection', function(socket){
      //on connection broadcast message to other connected users
      socket.broadcast.emit('connection', {connected: true, user: socket.handshake.query.user, namespace: schoolSocket.name +' namespace'});

      //add user to online users
      online_users_school.push(socket.handshake.query.user);

      socket.on('ready', function() {
          online_users_school.forEach(function(user, index) {
          socket.emit('connection', {connected: true, user: user, namespace: schoolSocket.name +' namespace'});
        });
      });

      //on disconnect event broadcast message to other connected users
      socket.on('disconnect', function(){
        //remove user from online users
        socket.broadcast.emit('connection', {connected: false, user: socket.handshake.query.user});
        online_users_school.splice(online_users_school.indexOf(socket.handshake.query.user), 1);
      });
    });*/

    return io;
};

module.exports.systemEmit = function(projectId, data){

  projectService.getProjectMembers(projectId, function(member_ids){
      if(member_ids !== null && member_ids !== undefined){
        /*
          data={
            projectId: projectId,
            userId: userId,
            content: content,

              }
        */
        var x;
        for(x in member_ids){
            outside_io.of('/notification').to('SELF_' + member_ids[x].id).emit("system", { data : data });
        }
      }
  });

};
<|endoftext|>


<commit_before>"use strict";

/**

 * Module dependencies

 */

var socketio = require('socket.io');
var messagingService  = require('../services/messagingService');
var channelService  = require('../services/channelService');
var projectService  = require('../services/projectService');
var models  = require('../models');
var socketioJwt = require('socketio-jwt');

var redis = require('socket.io-redis');
var outside_io = require("socket.io-emitter")({ host: '127.0.0.1', port: 6379 });
var winston = require('winston');

module.exports.listen = function(app){

    var io = socketio.listen(app);

    io.adapter(redis({ host: 'localhost', port: 6379 }));

    var message_socket = io.of('/messages');

    var notification_socket = io.of('/notification');

    var connected_clients = {};

    notification_socket.use(socketioJwt.authorize({
      secret: 'mySecretPassword',
      handshake: true
    }));

    message_socket.use(socketioJwt.authorize({
      secret: 'mySecretPassword',
      handshake: true
    }));

    //namespace to handle notifications
    notification_socket.on('connection', function(socket){

      socket.join('SELF_' + socket.decoded_token._id);

      socket.on('join-room', function(data){
        socket.join(data.room);

        messagingService.getProjectChannelsUpdates(data.projectId, data.userId, function(updates){
            socket.emit('channels-updates', updates);
        });

        //To this new online, send all the previously existent ones
        if(connected_clients[data.room] !== undefined){
          var x;
          for(x in connected_clients[data.room]){
            socket.emit("online-users", {type:"add", id: connected_clients[data.room][x].id});
          }
        }

        addToOnlineUsers(data.room, socket.decoded_token, function(){
          //Emit online user to all users in room
          notification_socket.to(data.room).emit("online-users", {type:"add", id: socket.decoded_token._id});
        });
      });

      //on ping save last activity date
      socket.on("ping", function(data) {
          messagingService.storeDisconnectionDate(data);
      });

      //on typing, broadcast everyone but typer
      socket.on("typing", function(data) {
          socket.broadcast.emit("typing", {typing: data.typing, msg: data.who + ' is typing..'});
      });

      socket.on('leave-room', function(data){
        socket.leave(data.room);
        removeFromOnlineUsers(data.room, socket.decoded_token, function(){
          //Emit online user to all users in room
          notification_socket.to(data.room).emit("online-users", {type:"remove", id: socket.decoded_token._id});
        });
      });

      socket.on('system', function(data){
        winston.info('data: ', data);
        /*
          data={
            projectId: projectId,
            userId: userId,
            content: content,

              }
        */

        projectService.getProjectMembers(data.projectId, function(member_ids){
            if(member_ids !== null && member_ids !== undefined){
              var memberId;
              for(memberId in member_ids){
                  socket.to('SELF_' + memberId).emit("system", { data : data });
                  winston.info("emiti al id: ", memberId);
              }
            }
        });
      });
    });

    //namespace to handle channel rooms and messages
    message_socket.on('connection', function(socket){
      socket.on('join-room', function(data){
        socket.join(data.room);
      });

      //on chat message, broadcast to everyone but sender
      socket.on('message', function(data){
        if(data.message.message.text.length <= models.Message.contentLength()){
          //set UTC +00 date before broadcast.
          data.message.message.date = new Date().getTime();
          //broadcast message to provided room.
          socket.broadcast.to(data.room).emit('message', data.message);
          if(isNaN(data.room)){
            //Direct channel
            notification_socket.to('SELF_' + data.message.message.destinationUser).emit("transient-notification", {type:"direct", id: data.message.message.user, projectId: data.message.message.projectId});
          } else {
            if(data.channel_type === 'P'){
              //Group and private channel

              //send notifications to each active member of the groupal private channel
              channelService.getChannelActiveMembers(data.room, function(members){
                  var x;
                  for(x in members){
                    notification_socket.to('SELF_' + members[x]).emit("transient-notification", {type:"private-channel", id: data.room, projectId: data.message.message.projectId});
                  }
              });
            } else {
              //Group and shared channel
              notification_socket.to(data.project_room).emit("transient-notification", {type:"channel", id: data.room});
            }
          }
          messagingService.storeMessage(data);
        } else {
          socket.emit('message-error', "message too long.");
        }
      });

      socket.on('leave-room', function(data){
        socket.leave(data.room);
      });

      socket.on('disconnect', function(){
      });
    });

    // Given a socket token, stores it at a room structure to keep track of online users.
    function addToOnlineUsers(room, decoded_token, callback){
      if(connected_clients[room] === undefined){
        connected_clients[room] = [];
      }

      //delete if existed
      connected_clients[room] = connected_clients[room]
             .filter(function (el) {
                      return el.id !== decoded_token._id;
                     });

      //add again
      connected_clients[room].push({id: decoded_token._id});
      callback();
    }

    function removeFromOnlineUsers(room, decoded_token, callback){
      if(connected_clients[room] !== undefined){

        connected_clients[room] = connected_clients[room]
               .filter(function (el) {
                        return el.id !== decoded_token._id;
                       });
      }

      callback();
    }

    /*notification_socket.on('connection', function(socket){
      //on connection broadcast message to other connected users
      socket.broadcast.emit('connection', {connected: true, user: socket.handshake.query.user, namespace: schoolSocket.name +' namespace'});

      //add user to online users
      online_users_school.push(socket.handshake.query.user);

      socket.on('ready', function() {
          online_users_school.forEach(function(user, index) {
          socket.emit('connection', {connected: true, user: user, namespace: schoolSocket.name +' namespace'});
        });
      });

      //on disconnect event broadcast message to other connected users
      socket.on('disconnect', function(){
        //remove user from online users
        socket.broadcast.emit('connection', {connected: false, user: socket.handshake.query.user});
        online_users_school.splice(online_users_school.indexOf(socket.handshake.query.user), 1);
      });
    });*/

    return io;
};

module.exports.systemEmit = function(projectId, data){

  projectService.getProjectMembers(projectId, function(member_ids){
      if(member_ids !== null && member_ids !== undefined){
        /*
          data={
            projectId: projectId,
            userId: userId,
            content: content,

              }
        */
        var x;
        for(x in member_ids){
            outside_io.of('/notification').to('SELF_' + member_ids[x].id).emit("system", { data : data });
        }
      }
  });

};

module.exports.broadcastIntegrationMessage = function (project_room, room, message){
  outside_io.of('/messages').to(room).emit('message', message);
  outside_io.of('/notification').to(project_room).emit('transient-notification', {type:"channel", id: room});
};

module.exports.broadcastVideocallMessage = function (project_room, room, message){
  outside_io.of('/messages').to(room).emit('message', message);
  outside_io.of('/notification').to(project_room).emit('transient-notification', {type:"channel", id: room});
};
<commit_msg>agrego user id de usuario generador de una notificacion, para poder filtrarla en el cliente<commit_after>"use strict";

/**

 * Module dependencies

 */

var socketio = require('socket.io');
var messagingService  = require('../services/messagingService');
var channelService  = require('../services/channelService');
var projectService  = require('../services/projectService');
var models  = require('../models');
var socketioJwt = require('socketio-jwt');

var redis = require('socket.io-redis');
var outside_io = require("socket.io-emitter")({ host: '127.0.0.1', port: 6379 });
var winston = require('winston');

module.exports.listen = function(app){

    var io = socketio.listen(app);

    io.adapter(redis({ host: 'localhost', port: 6379 }));

    var message_socket = io.of('/messages');

    var notification_socket = io.of('/notification');

    var connected_clients = {};

    notification_socket.use(socketioJwt.authorize({
      secret: 'mySecretPassword',
      handshake: true
    }));

    message_socket.use(socketioJwt.authorize({
      secret: 'mySecretPassword',
      handshake: true
    }));

    //namespace to handle notifications
    notification_socket.on('connection', function(socket){

      socket.join('SELF_' + socket.decoded_token._id);

      socket.on('join-room', function(data){
        socket.join(data.room);

        messagingService.getProjectChannelsUpdates(data.projectId, data.userId, function(updates){
            socket.emit('channels-updates', updates);
        });

        //To this new online, send all the previously existent ones
        if(connected_clients[data.room] !== undefined){
          var x;
          for(x in connected_clients[data.room]){
            socket.emit("online-users", {type:"add", id: connected_clients[data.room][x].id});
          }
        }

        addToOnlineUsers(data.room, socket.decoded_token, function(){
          //Emit online user to all users in room
          notification_socket.to(data.room).emit("online-users", {type:"add", id: socket.decoded_token._id});
        });
      });

      //on ping save last activity date
      socket.on("ping", function(data) {
          messagingService.storeDisconnectionDate(data);
      });

      //on typing, broadcast everyone but typer
      socket.on("typing", function(data) {
          socket.broadcast.emit("typing", {typing: data.typing, msg: data.who + ' is typing..'});
      });

      socket.on('leave-room', function(data){
        socket.leave(data.room);
        removeFromOnlineUsers(data.room, socket.decoded_token, function(){
          //Emit online user to all users in room
          notification_socket.to(data.room).emit("online-users", {type:"remove", id: socket.decoded_token._id});
        });
      });

      socket.on('system', function(data){
        winston.info('data: ', data);
        /*
          data={
            projectId: projectId,
            userId: userId,
            content: content,

              }
        */

        projectService.getProjectMembers(data.projectId, function(member_ids){
            if(member_ids !== null && member_ids !== undefined){
              var memberId;
              for(memberId in member_ids){
                  socket.to('SELF_' + memberId).emit("system", { data : data });
                  winston.info("emiti al id: ", memberId);
              }
            }
        });
      });
    });

    //namespace to handle channel rooms and messages
    message_socket.on('connection', function(socket){
      socket.on('join-room', function(data){
        socket.join(data.room);
      });

      //on chat message, broadcast to everyone but sender
      socket.on('message', function(data){
        if(data.message.message.text.length <= models.Message.contentLength()){
          //set UTC +00 date before broadcast.
          data.message.message.date = new Date().getTime();
          //broadcast message to provided room.
          socket.broadcast.to(data.room).emit('message', data.message);
          if(isNaN(data.room)){
            //Direct channel
            notification_socket.to('SELF_' + data.message.message.destinationUser).emit("transient-notification", {type:"direct", id: data.message.message.user, projectId: data.message.message.projectId});
          } else {
            if(data.channel_type === 'P'){
              //Group and private channel

              //send notifications to each active member of the groupal private channel
              channelService.getChannelActiveMembers(data.room, function(members){
                  var x;
                  for(x in members){
                    notification_socket.to('SELF_' + members[x]).emit("transient-notification", {type:"private-channel", id: data.room, projectId: data.message.message.projectId, source_user_id: data.message.message.user});
                  }
              });
            } else {
              //Group and shared channel
              notification_socket.to(data.project_room).emit("transient-notification", {type:"channel", id: data.room, source_user_id: data.message.message.user});
            }
          }
          messagingService.storeMessage(data);
        } else {
          socket.emit('message-error', "message too long.");
        }
      });

      socket.on('leave-room', function(data){
        socket.leave(data.room);
      });

      socket.on('disconnect', function(){
      });
    });

    // Given a socket token, stores it at a room structure to keep track of online users.
    function addToOnlineUsers(room, decoded_token, callback){
      if(connected_clients[room] === undefined){
        connected_clients[room] = [];
      }

      //delete if existed
      connected_clients[room] = connected_clients[room]
             .filter(function (el) {
                      return el.id !== decoded_token._id;
                     });

      //add again
      connected_clients[room].push({id: decoded_token._id});
      callback();
    }

    function removeFromOnlineUsers(room, decoded_token, callback){
      if(connected_clients[room] !== undefined){

        connected_clients[room] = connected_clients[room]
               .filter(function (el) {
                        return el.id !== decoded_token._id;
                       });
      }

      callback();
    }

    /*notification_socket.on('connection', function(socket){
      //on connection broadcast message to other connected users
      socket.broadcast.emit('connection', {connected: true, user: socket.handshake.query.user, namespace: schoolSocket.name +' namespace'});

      //add user to online users
      online_users_school.push(socket.handshake.query.user);

      socket.on('ready', function() {
          online_users_school.forEach(function(user, index) {
          socket.emit('connection', {connected: true, user: user, namespace: schoolSocket.name +' namespace'});
        });
      });

      //on disconnect event broadcast message to other connected users
      socket.on('disconnect', function(){
        //remove user from online users
        socket.broadcast.emit('connection', {connected: false, user: socket.handshake.query.user});
        online_users_school.splice(online_users_school.indexOf(socket.handshake.query.user), 1);
      });
    });*/

    return io;
};

module.exports.systemEmit = function(projectId, data){

  projectService.getProjectMembers(projectId, function(member_ids){
      if(member_ids !== null && member_ids !== undefined){
        /*
          data={
            projectId: projectId,
            userId: userId,
            content: content,

              }
        */
        var x;
        for(x in member_ids){
            outside_io.of('/notification').to('SELF_' + member_ids[x].id).emit("system", { data : data });
        }
      }
  });

};

module.exports.broadcastIntegrationMessage = function (project_room, room, message){
  outside_io.of('/messages').to(room).emit('message', message);
  outside_io.of('/notification').to(project_room).emit('transient-notification', {type:"channel", id: room});
};

module.exports.broadcastVideocallMessage = function (project_room, room, message){
  outside_io.of('/messages').to(room).emit('message', message);
  outside_io.of('/notification').to(project_room).emit('transient-notification', {type:"channel", id: room});
};
<|endoftext|>


<commit_before>/**
 * Created by JFog on 6/9/15.
 */
var TIME_LOOP = 30;
var ALARM_SOUND = '/sound/alarm.mp3';

jQuery(document).ready(function($) {

    // run after each TIME_LOOP(s)
    setInterval(findUnreadWarning, TIME_LOOP * 1000);

    function findUnreadWarning() {
        $.ajax({
            url: '/warning/default/cron-unread',
            type: 'post',
            data: {

            },
            beforeSend: function() {
                // do something before send
            },
            success: function(json) {
                var data = $.parseJSON(json);
                if (data['html']) {

                    if ($('#latest-warning-block').hasClass('show')) {

                    } else {

                        // open popup
                        $('#latest-warning-block').dialogBox({
                            type: 'correct',  //three type:'normal'(default),'correct','error',
                            width: 1000,
                            height: 400,
                            hasMask: true,
                            autoHide: false,
                            time: 3000,
                            effect: 'fall',
                            title: 'Cảnh báo mới',
                            content: data['html']
                        });

                        // turn on alarm sound
                        playSound();

                        // gallery
                        $('.gallery').each(function() {
                            $(this).magnificPopup({
                                delegate: 'button',
                                type: 'image',
                                gallery: {
                                    enabled:true
                                }
                            });
                        });

                    }

                }
            }
        });
    }

    function playSound() {
        var audioElement = document.createElement('audio');
        audioElement.setAttribute('src', ALARM_SOUND);
        audioElement.setAttribute('autoplay', 'autoplay');
        audioElement.play();
    }

    $(document).on('click', '.do-read', function() {
        var warning = $(this).parent().parent().parent().parent();
        var id = warning.attr('id');
        var stationHref = warning.attr('station-href');

        $.ajax({
            'method' : 'post',
            'url' : '/warning/default/read',
            'data' : {
                'warning_id' : id
            },
            'beforeSend' : function() {
                warning.find('td').css('background-color', 'white !important');
            },
            'success' : function(data) {
                warning.removeClass('unread');
                warning.addClass('read');
            }
        });
    });

});
<commit_msg>update<commit_after>/**
 * Created by JFog on 6/9/15.
 */
var TIME_LOOP = 15;
var ALARM_SOUND = '/sound/alarm.mp3';

jQuery(document).ready(function($) {

    // run after each TIME_LOOP(s)
    setInterval(findUnreadWarning, TIME_LOOP * 1000);

    function findUnreadWarning() {
        $.ajax({
            url: '/warning/default/cron-unread',
            type: 'post',
            data: {

            },
            beforeSend: function() {
                // do something before send
            },
            success: function(json) {
                var data = $.parseJSON(json);
                if (data['html']) {

                    if ($('#latest-warning-block').hasClass('show')) {

                    } else {

                        // open popup
                        $('#latest-warning-block').dialogBox({
                            type: 'correct',  //three type:'normal'(default),'correct','error',
                            width: 1000,
                            height: 400,
                            hasMask: true,
                            autoHide: false,
                            time: 3000,
                            effect: 'fall',
                            title: 'Cảnh báo mới',
                            content: data['html']
                        });

                        // turn on alarm sound
                        playSound();

                        // gallery
                        $('.gallery').each(function() {
                            $(this).magnificPopup({
                                delegate: 'button',
                                type: 'image',
                                gallery: {
                                    enabled:true
                                }
                            });
                        });

                    }

                }
            }
        });
    }

    function playSound() {
        var audioElement = document.createElement('audio');
        audioElement.setAttribute('src', ALARM_SOUND);
        audioElement.setAttribute('autoplay', 'autoplay');
        audioElement.play();
    }

    $(document).on('click', '.do-read', function() {
        var warning = $(this).parent().parent().parent().parent();
        var id = warning.attr('id');
        var stationHref = warning.attr('station-href');

        $.ajax({
            'method' : 'post',
            'url' : '/warning/default/read',
            'data' : {
                'warning_id' : id
            },
            'beforeSend' : function() {
                warning.find('td').css('background-color', 'white !important');
            },
            'success' : function(data) {
                warning.removeClass('unread');
                warning.addClass('read');
            }
        });
    });

});
<|endoftext|>