From e92be70f164d8d8fb172464539fdb80f3cc35f0d Mon Sep 17 00:00:00 2001
From: marudor <marudor@marudor.de>
Date: Sat, 18 Feb 2017 20:00:44 +0100
Subject: [PATCH] eslint

---
 .eslintignore       |   1 +
 .eslintrc.js        |  13 +
 main.js             |  41 +-
 modules/brand.js    |  94 ++---
 modules/bus.js      | 187 ++++-----
 modules/calendar.js | 211 +++++-----
 modules/date.js     |  26 +-
 modules/diagrams.js |  90 ++--
 modules/irc.js      |  67 +--
 modules/weather.js  | 160 ++++---
 package.json        |   6 +-
 yarn.lock           | 994 +++++++++++++++++++++++++++++++++++++++++++-
 12 files changed, 1440 insertions(+), 450 deletions(-)
 create mode 100644 .eslintignore
 create mode 100644 .eslintrc.js

diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..364fdec
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+public/
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..78ee61a
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,13 @@
+module.exports = {
+  extends: 'marudor/noReact',
+  env: {
+    node: true,
+  },
+  globals: {
+    pad: false,
+    DOW: false,
+  },
+  rules: {
+    'header/header': 0,
+  }
+}
diff --git a/main.js b/main.js
index 349ea00..a6191c0 100644
--- a/main.js
+++ b/main.js
@@ -1,20 +1,21 @@
-var express = require('express');
-var app = express();
-var server = require('http').Server(app);
-var io = require('socket.io')(server);
+/* eslint no-console: 0 */
+const express = require('express');
+const app = express();
+const server = require('http').Server(app);
+const io = require('socket.io')(server);
 
 server.listen(8000);
 
-app.use(express.static(__dirname + '/public'));
+app.use(express.static(`${__dirname }/public`));
 
-var instanceClients = [];
-io.on('connection', function (socket) {
-    socket.on('ident', function (client) {
+const instanceClients = [];
+io.on('connection', (socket) => {
+    socket.on('ident', (client) => {
         if (instanceClients.indexOf(client) === -1) {
             instanceClients.push(client);
             socket.emit('meta', 'reload');
         }
-    })
+    });
 });
 
 function endsWith(str, suffix) {
@@ -22,21 +23,21 @@ function endsWith(str, suffix) {
 }
 
 // for reasons
-DOW = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
-pad = function (n, width, z) {
-    z = z || '0';
-    n = n + '';
+global.DOW = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+global.pad = function(n, width, z = '0') {
+    // eslint-disable-next-line
+    n = String(n);
     return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
-}
+};
 
-var normalizedPath = require("path").join(__dirname, "modules");
-require("fs").readdirSync(normalizedPath).forEach(function(file) {
-    if (endsWith(file,'.js')) {
+const normalizedPath = require('path').join(__dirname, 'modules');
+require('fs').readdirSync(normalizedPath).forEach((file) => {
+    if (endsWith(file, '.js')) {
         try {
-            require("./modules/" + file)(io);
-            console.log(file+" loaded");
+            require(`./modules/${ file}`)(io);
+            console.log(`${file} loaded`);
         } catch (e) {
-            console.log("Error loading "+file);
+            console.log(`Error loading ${file}`);
             console.log(e);
         }
     }
diff --git a/modules/brand.js b/modules/brand.js
index a45ae69..a144558 100644
--- a/modules/brand.js
+++ b/modules/brand.js
@@ -1,59 +1,59 @@
-var httpreq = require('httpreq');
-var Mustache = require('mustache');
+const httpreq = require('httpreq');
+const Mustache = require('mustache');
 
-var URL = 'https://stratum0.org/status/status.json';
-var TEMPLATES = {};
-require('fs').readFile('modules/brand/template.mustache', 'utf-8', function (err, data) {
-    TEMPLATES.template = data;
+const URL = 'https://stratum0.org/status/status.json';
+const TEMPLATES = {};
+require('fs').readFile('modules/brand/template.mustache', 'utf-8', (err, data) => {
+  TEMPLATES.template = data;
 });
-require('fs').readFile('modules/brand/status.mustache', 'utf-8', function (err, data) {
-    TEMPLATES.status = data;
+require('fs').readFile('modules/brand/status.mustache', 'utf-8', (err, data) => {
+  TEMPLATES.status = data;
 });
 
-var status = {};
+let status = {};
 
 function renderStatus(sock, everything) {
-    var sendInner = function () {
-        status.random = ''+Math.random();
-        sock.emit('brand.status', Mustache.render(TEMPLATES.status, status));
-    }
-    if (everything) {
-        sock.emit('brand', Mustache.render(TEMPLATES.template, {}));
-        setTimeout(sendInner, 3000);
-    } else {
-        sendInner();
-    }
+  const sendInner = function() {
+    status.random = `${Math.random()}`;
+    sock.emit('brand.status', Mustache.render(TEMPLATES.status, status));
+  };
+  if (everything) {
+    sock.emit('brand', Mustache.render(TEMPLATES.template, {}));
+    setTimeout(sendInner, 3000);
+  } else {
+    sendInner();
+  }
 }
 
 function fetchStatus(cb) {
-    httpreq.get(URL, function (err, res) {
-        var state = JSON.parse(res.body).state;
-        cb(state);
-    });
+  httpreq.get(URL, (err, res) => {
+    const state = JSON.parse(res.body).state;
+    cb(state);
+  });
 }
 
-module.exports = function (io) {
-    var firstTime = true;
-    function update() {
-        fetchStatus(function (state) {
-            if (status.lastchange != state.lastchange) {
-                var d = new Date(state.lastchange*1000);
-                state.since = DOW[d.getDay()]+', '+pad(d.getHours(),2)+':'
-                    +pad(d.getMinutes(),2);
-                status = state;
-                renderStatus(io);
-            }
-            if (firstTime && status) {
-                io.on('connection', function (sock) {
-                    renderStatus(sock, true);
-                });
-                renderStatus(io, true);
-                firstTime = false;
-            } else {
-                renderStatus(io, false);
-            }
+module.exports = function(io) {
+  let firstTime = true;
+  function update() {
+    fetchStatus((state) => {
+      if (status.lastchange !== state.lastchange) {
+        const d = new Date(state.lastchange * 1000);
+        state.since = `${DOW[d.getDay()]}, ${pad(d.getHours(), 2)}:${
+        pad(d.getMinutes(), 2)}`;
+        status = state;
+        renderStatus(io);
+      }
+      if (firstTime && status) {
+        io.on('connection', (sock) => {
+          renderStatus(sock, true);
         });
-    }
-    setInterval(update, 2*60*1000); //every 2 minutes
-    update();
-}
+        renderStatus(io, true);
+        firstTime = false;
+      } else {
+        renderStatus(io, false);
+      }
+    });
+  }
+  setInterval(update, 2 * 60 * 1000); //every 2 minutes
+  update();
+};
diff --git a/modules/bus.js b/modules/bus.js
index 552a4e4..fb3c675 100644
--- a/modules/bus.js
+++ b/modules/bus.js
@@ -1,121 +1,116 @@
-var fs = require('fs');
-var Mustache = require('mustache');
-var XML = require('pixl-xml');
-var httpreq = require('httpreq');
+/* eslint no-mixed-operators: 0 */
+const fs = require('fs');
+const Mustache = require('mustache');
+const XML = require('pixl-xml');
+const httpreq = require('httpreq');
 
 /// CONFIG
-var CITY = 'Braunschweig';
-var STOPS = ['Ludwigstraße','Hamburger Straße'];
-var ENTRIES = 6;
+const CITY = 'Braunschweig';
+const STOPS = ['Ludwigstraße', 'Hamburger Straße'];
+const ENTRIES = 6;
 
 /// VARS
-var CACHED = [];
-var TEMPLATES = {};
-fs.readFile('modules/bus/outer.mustache', 'utf-8', function (err, data) {
-    TEMPLATES.outer = data;
+let CACHED = [];
+const TEMPLATES = {};
+fs.readFile('modules/bus/outer.mustache', 'utf-8', (err, data) => {
+  TEMPLATES.outer = data;
 });
-fs.readFile('modules/bus/inner.mustache', 'utf-8', function (err, data) {
-    TEMPLATES.inner = data;
+fs.readFile('modules/bus/inner.mustache', 'utf-8', (err, data) => {
+  TEMPLATES.inner = data;
 });
 
-/// FUNS
-function pad(n, width, z) {
-    z = z || '0';
-    n = n + '';
-    return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
-}
-
 function fetchData(stop, cb) {
-    var url = "http://62.154.206.87/efaws2/default/XML_DM_REQUEST?sessionID=0&requestID=0&language=de&useRealtime=1&coordOutputFormat=WGS84[DD.ddddd]&locationServerActive=1&mode=direct&dmLineSelectionAll=1&depType=STOPEVENTS&useAllStops=1&command=null&type_dm=stop&name_dm="+CITY+' '+stop+"&mId=efa_rc2"
-    httpreq.get(url, {binary: true}, function (err, res) {
-        try {
-            cb(XML.parse(res.body));
-        } catch(e) {
-        }
-    });
+  const url = `http://62.154.206.87/efaws2/default/XML_DM_REQUEST?sessionID=0&requestID=0&language=de&useRealtime=1&coordOutputFormat=WGS84[DD.ddddd]&locationServerActive=1&mode=direct&dmLineSelectionAll=1&depType=STOPEVENTS&useAllStops=1&command=null&type_dm=stop&name_dm=${ CITY } ${ stop }&mId=efa_rc2`;
+  httpreq.get(url, { binary: true }, (err, res) => {
+    try {
+      cb(XML.parse(res.body));
+    } catch (e) {
+      // Swallow
+    }
+  });
 }
 
 function renderLine(line) {
-    var image = '';
-    if (line.charAt(0) == "M") {
-        image = 'metro.svg';
-        line = line.substr(1);
-    } else if (line.length < 3) {
-        image = 'tram.svg';
-    } else {
-        image = 'bus.svg';
-    }
-    return '<img src="/modules/bus/'+image+'"> '+line;
+  let image = '';
+  if (line.charAt(0) === 'M') {
+    image = 'metro.svg';
+    line = line.substr(1); // eslint-disable-line
+  } else if (line.length < 3) {
+    image = 'tram.svg';
+  } else {
+    image = 'bus.svg';
+  }
+  return `<img src="/modules/bus/${image}"> ${line}`;
 }
 
 function getData(stop, count, cb) {
-    fetchData(stop, function (data) {
-        var deps = data.itdDepartureMonitorRequest.itdDepartureList.itdDeparture;
-        cb(deps.slice(0, count).map(function (dep) {
-            return {
-                line: dep.itdServingLine.symbol,
-                renderedLine: renderLine(dep.itdServingLine.symbol),
-                dir: dep.itdServingLine.direction.replace(CITY, '').trim(),
-                platform: dep.platform,
-                mean: dep.itdServingLine.itdNoTrain.name,
-                day: pad(dep.itdDateTime.itdDate.day,2),
-                month: pad(dep.itdDateTime.itdDate.month,2),
-                hour: pad(dep.itdDateTime.itdTime.hour,2),
-                minute: pad(dep.itdDateTime.itdTime.minute,2)
-            };
-        }));
-    });
+  fetchData(stop, (data) => {
+    const deps = data.itdDepartureMonitorRequest.itdDepartureList.itdDeparture;
+    cb(deps.slice(0, count).map((dep) => ({
+      line: dep.itdServingLine.symbol,
+      renderedLine: renderLine(dep.itdServingLine.symbol),
+      dir: dep.itdServingLine.direction.replace(CITY, '').trim(),
+      platform: dep.platform,
+      mean: dep.itdServingLine.itdNoTrain.name,
+      day: pad(dep.itdDateTime.itdDate.day, 2),
+      month: pad(dep.itdDateTime.itdDate.month, 2),
+      hour: pad(dep.itdDateTime.itdTime.hour, 2),
+      minute: pad(dep.itdDateTime.itdTime.minute, 2),
+    })));
+  });
 }
 
 function update(io, allStopsDoneCb) {
-    var done = [];
-    var context = [];
-    var innerGetData = function (stop, i) {
-        var ns = normalizeStop(stop);
-        getData(stop, ENTRIES, function (deps) {
-            try {
-                context[i] = {stop: stop, normalizedStop: ns, deps: deps};
-                io.emit('bus.'+ns, Mustache.render(TEMPLATES.inner, context[i]));
-                if (done.indexOf(stop) === -1) {
-                    done.push(stop);
-                    if (done.length === STOPS.length) {
-                        allStopsDoneCb();
-                    }
-                }
-                CACHED = context;
-            } catch (e) {console.log(e);}
-            // calculate when to update next
-            var d = new Date();
-            var hour = d.getHours();
-            var minute = d.getMinutes();
-            var depHour = deps[0].hour < hour ? deps[0].hour+24 : deps[0].hour;
-            var diff = (depHour-hour)*60 + (deps[0].minute-minute);
-            setTimeout(function () {
-                innerGetData(stop, i);
-            }, (diff * 60 + (60-d.getSeconds()) % 60) * 1000);
-        });
-    }
-    STOPS.forEach(function (stop, i) {
+  const done = [];
+  const context = [];
+  const innerGetData = function(stop, i) {
+    const ns = normalizeStop(stop);
+    getData(stop, ENTRIES, (deps) => {
+      try {
+        context[i] = { stop, normalizedStop: ns, deps };
+        io.emit(`bus.${ns}`, Mustache.render(TEMPLATES.inner, context[i]));
+        if (done.indexOf(stop) === -1) {
+          done.push(stop);
+          if (done.length === STOPS.length) {
+            allStopsDoneCb();
+          }
+        }
+        CACHED = context;
+      } catch (e) {
+        console.log(e); // eslint-disable-line
+      }
+      // calculate when to update next
+      const d = new Date();
+      const hour = d.getHours();
+      const minute = d.getMinutes();
+      const depHour = deps[0].hour < hour ? deps[0].hour + 24 : deps[0].hour;
+      const diff = (depHour - hour) * 60 + (deps[0].minute - minute);
+      setTimeout(() => {
         innerGetData(stop, i);
+      }, (diff * 60 + (60 - d.getSeconds()) % 60) * 1000);
     });
+  };
+  STOPS.forEach((stop, i) => {
+    innerGetData(stop, i);
+  });
 }
 
 function normalizeStop(stop) {
-    return stop.replace(/[^a-zA-Z0-9_]/g,'');
+  return stop.replace(/[^a-zA-Z0-9_]/g, '');
 }
 
-module.exports = function (io) {
-    update(io, function () {
-        var pushToClient = function (sock) {
-            sock.emit('bus', Mustache.render(TEMPLATES.outer, CACHED));
-            setTimeout(function () {
-                for (var i in CACHED) {
-                    sock.emit('bus.'+CACHED[i].normalizedStop,
-                        Mustache.render(TEMPLATES.inner, CACHED[i]));
-                }
-            }, 3000); //wait a second to let the client process the outlets
-        };
-        io.on('connect', pushToClient);
-        pushToClient(io);
+module.exports = function(io) {
+  update(io, () => {
+    const pushToClient = function(sock) {
+      sock.emit('bus', Mustache.render(TEMPLATES.outer, CACHED));
+      setTimeout(() => {
+        for (const i in CACHED) { // eslint-disable-line
+          sock.emit(`bus.${CACHED[i].normalizedStop}`,
+            Mustache.render(TEMPLATES.inner, CACHED[i]));
+          }
+        }, 3000); //wait a second to let the client process the outlets
+      };
+      io.on('connect', pushToClient);
+      pushToClient(io);
     });
-}
+  };
diff --git a/modules/calendar.js b/modules/calendar.js
index ff7fd86..c8490df 100644
--- a/modules/calendar.js
+++ b/modules/calendar.js
@@ -1,124 +1,111 @@
-var httpreq = require('httpreq');
-var ical = require('ical.js');
-var Mustache = require('mustache');
-var time = require('time');
+/* eslint no-mixed-operators: 0 */
+const httpreq = require('httpreq');
+const ical = require('ical.js');
+const Mustache = require('mustache');
+const time = require('time');
 
-var URL = 'https://stratum0.org/kalender/termine.ics';
-var TEMPLATE = '';
-require('fs').readFile('modules/calendar/template.mustache', 'utf-8', function (err, data) {
-    TEMPLATE = data;
+const URL = 'https://stratum0.org/kalender/termine.ics';
+let TEMPLATE = '';
+require('fs').readFile('modules/calendar/template.mustache', 'utf-8', (err, data) => {
+  TEMPLATE = data;
 });
-var CALENDAR;
+let CALENDAR;
 
-var TZOFFSET = new time.Date().getTimezoneOffset()*60;
+const TZOFFSET = new time.Date().getTimezoneOffset() * 60;
 
-function pad(n, width, z) {
-    z = z || '0';
-    n = n + '';
-    return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
-}
-
-function parseDate(s) {
-    var i = parseInt;
-    if (s.indexOf('T') > -1) {
-        return new Date(i(s.substr(0,4)), i(s.substr(4,2))-1, i(s.substr(6,2)),
-            i(s.substr(9,2)), i(s.substr(11,2)), i(s.substr(13,2)));
-    } else {
-        return new Date(i(s.substr(0,4)), i(s.substr(4,2))-1, i(s.substr(6,2)));
-    }
-}
 
 function getData(count, cb) {
-    httpreq.get(URL, function (err, res) {
-        var ics = res.body.replace(/[0-9]{8}T[0-9]{6}/g, '$&Z');
-        var cal = new ical.Component(ical.parse(ics));
-        var rawEvents = cal.getAllSubcomponents('vevent').map(function (raw) {
-            return new ical.Event(raw);
-        });
-        var events = [];
-        var ev, p = function (p) {return ev.component.getFirstPropertyValue(p);};
-        for (var i in rawEvents) {
-            ev = rawEvents[i];
-            if (ev.isRecurring()) {
-                var iter = ev.iterator();
-                var duration = p('dtend').toUnixTime()-p('dtstart').toUnixTime();
-                for (var i = 0; i < 100; i++) {
-                    var next = iter.next();
-                    if (next === undefined) {break;}
-                    var start = next.toUnixTime()+TZOFFSET;
-                    events.push({
-                        title: p('summary'),
-                        start: start,
-                        end: start + duration
-                    });
-                }
-            } else {
-                events.push({
-                    title: p('summary'),
-                    start: p('dtstart').toUnixTime()+TZOFFSET,
-                    end: p('dtend').toUnixTime()+TZOFFSET,
-                });
-            }
+  httpreq.get(URL, (err, res) => {
+    const ics = res.body.replace(/[0-9]{8}T[0-9]{6}/g, '$&Z');
+    const cal = new ical.Component(ical.parse(ics));
+    const rawEvents = cal.getAllSubcomponents('vevent').map((raw) => new ical.Event(raw));
+    const events = [];
+    const p = function(p) {
+      return ev.component.getFirstPropertyValue(p);
+    };
+    let ev = p;
+    for (const i in rawEvents) { // eslint-disable-line
+      ev = rawEvents[i];
+      if (ev.isRecurring()) {
+        const iter = ev.iterator();
+        const duration = p('dtend').toUnixTime() - p('dtstart').toUnixTime();
+        for (let i = 0; i < 100; i++) {
+          const next = iter.next();
+          if (next === undefined) {
+            break;
+          }
+          const start = next.toUnixTime() + TZOFFSET;
+          events.push({
+            title: p('summary'),
+            start,
+            end: start + duration,
+          });
         }
-        events.sort(function (a, b) {
-            return a.start - b.start;
+      } else {
+        events.push({
+          title: p('summary'),
+          start: p('dtstart').toUnixTime() + TZOFFSET,
+          end: p('dtend').toUnixTime() + TZOFFSET,
         });
-        var threshold = Date.now()/1000 - 5*60*60; //show 5 hours ago
-        var i;
-        for (i in events) {
-            if (events[i].end > threshold) {
-                i = parseInt(i);
-                break;
-            }
+      }
+    }
+    events.sort((a, b) => a.start - b.start);
+    const threshold = Date.now() / 1000 - 5 * 60 * 60; //show 5 hours ago
+    let i;
+    for (i in events) {
+      if (events[i].end > threshold) {
+        i = parseInt(i, 10);
+        break;
+      }
+    }
+    const now = new Date();
+    cb(events.slice(i, i + count).map((ev) => {
+      const start = new Date(ev.start * 1000);
+      if (start.getMonth() === now.getMonth() && start.getDate() === now.getDate()) {
+        ev.startRendered = `${pad(start.getHours(), 2)}:${pad(start.getMinutes(), 2)}`;
+      } else {
+        ev.startRendered = `${DOW[start.getDay()]}, ${pad(start.getDate(), 2)
+        }.${pad(start.getMonth() + 1, 2)}. ${pad(start.getHours(), 2)
+        }:${pad(start.getMinutes(), 2)}`;
+      }
+      const end = new Date(ev.end * 1000);
+      if (ev.end - ev.start >= 60 * 60 * 24) {
+        ev.endRendered = `${DOW[end.getDay()]} ${pad(end.getHours(), 2)
+        }:${pad(end.getMinutes(), 2)}`;
+      } else {
+        ev.endRendered = `${pad(end.getHours(), 2)}:${pad(end.getMinutes(), 2)}`;
+      }
+      const dur = Math.floor((ev.end - ev.start) / 60);
+      ev.duration = `${pad(Math.floor(dur / 60), 2) }:${ pad((dur % 60), 2)}`;
+      if (start.getTime() < now.getTime()) {
+        if (end.getTime() < now.getTime()) {
+          ev.past = true;
+        } else {
+          ev.now = true;
         }
-        var now = new Date();
-        cb(events.slice(i, i+count).map(function (ev) {
-            var start = new Date(ev.start*1000);
-            if (start.getMonth() == now.getMonth() && start.getDate() == now.getDate()) {
-                ev.startRendered = pad(start.getHours(),2)+':'+pad(start.getMinutes(),2);
-            } else {
-                ev.startRendered = DOW[start.getDay()]+', '+pad(start.getDate(),2)
-                    +'.'+pad(start.getMonth()+1,2)+'. '+pad(start.getHours(),2)
-                    +':'+pad(start.getMinutes(),2);
-            }
-            var end = new Date(ev.end*1000);
-            if (ev.end - ev.start >= 60*60*24) {
-                ev.endRendered = DOW[end.getDay()]+' '+pad(end.getHours(),2)
-                    +':'+pad(end.getMinutes(),2);
-            } else {
-                ev.endRendered = pad(end.getHours(),2)+':'+pad(end.getMinutes(),2);
-            }
-            var dur = Math.floor((ev.end-ev.start)/60);
-            ev.duration = pad(Math.floor(dur/60),2)+':'+pad((dur%60),2)
-            if (start.getTime() < now.getTime()) {
-                if (end.getTime() < now.getTime()) {
-                    ev.past = true;
-                } else {
-                    ev.now = true;
-                }
-            }
-            return ev
-        }));
-    });
+      }
+      return ev;
+    }));
+  });
 }
 
-module.exports = function (io) {
-    function update(firstRunCallback) {
-        getData(8, function (data) {
-            CALENDAR = data;
-            io.emit('calendar', Mustache.render(TEMPLATE, CALENDAR));
-            if (firstRunCallback) {
-                firstRunCallback()
-                firstRunCallback = null;
-            }
-        });
-    }
-    update(function () {
-        var pushToClients = function (sock) {
-            sock.emit('calendar', Mustache.render(TEMPLATE, CALENDAR));
-        };
-        io.on('connect', pushToClients);
-        pushToClients(io);
+module.exports = function(io) {
+  function update(firstRunCallback) {
+    getData(8, (data) => {
+      CALENDAR = data;
+      io.emit('calendar', Mustache.render(TEMPLATE, CALENDAR));
+      if (firstRunCallback) {
+        firstRunCallback();
+        firstRunCallback = null; // eslint-disable-line
+      }
     });
-    setInterval(update, 600000);
-}
+  }
+  update(() => {
+    const pushToClients = function(sock) {
+      sock.emit('calendar', Mustache.render(TEMPLATE, CALENDAR));
+    };
+    io.on('connect', pushToClients);
+    pushToClients(io);
+  });
+  setInterval(update, 600000);
+};
diff --git a/modules/date.js b/modules/date.js
index 01f030d..c00d1dc 100644
--- a/modules/date.js
+++ b/modules/date.js
@@ -1,19 +1,13 @@
-function pad(n, width, z) {
-    z = z || '0';
-    n = n + '';
-    return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
-}
-
 function date() {
-    var d = new Date();
-    return DOW[d.getDay()]+', '+
-        pad(d.getDate(),2)+'.'+pad(d.getMonth()+1,2)+'.'+d.getFullYear()+' '+
-        pad(d.getHours(),2)+':'+pad(d.getMinutes(),2)+':'+pad(d.getSeconds(),2);
-}
+  const d = new Date();
+  return `${DOW[d.getDay()]}, ${
+    pad(d.getDate(), 2)}.${pad(d.getMonth() + 1, 2)}.${d.getFullYear()} ${
+      pad(d.getHours(), 2)}:${pad(d.getMinutes(), 2)}:${pad(d.getSeconds(), 2)}`;
+    }
 
 
-module.exports = function (io) {
-    setInterval(function () {
-        io.emit('date', '<div align="right"><h2>'+date()+'&nbsp;</h2></div>');
-    }, 1000);
-}
+    module.exports = function(io) {
+      setInterval(() => {
+        io.emit('date', `<div align="right"><h2>${date()}&nbsp;</h2></div>`);
+      }, 1000);
+    };
diff --git a/modules/diagrams.js b/modules/diagrams.js
index fa212ba..0218e40 100644
--- a/modules/diagrams.js
+++ b/modules/diagrams.js
@@ -1,60 +1,64 @@
-var Mustache = require('mustache');
-var httpreq = require('httpreq');
+const Mustache = require('mustache');
+const httpreq = require('httpreq');
 
-var TEMPLATES = {main: ''};
-require('fs').readFile('modules/diagrams/main.mustache', 'utf-8', function (err, data) {
-    TEMPLATES.main = data;
+const TEMPLATES = { main: '' };
+require('fs').readFile('modules/diagrams/main.mustache', 'utf-8', (err, data) => {
+  TEMPLATES.main = data;
 });
-require('fs').readFile('modules/diagrams/data.mustache', 'utf-8', function (err, data) {
-    TEMPLATES.data = data;
+require('fs').readFile('modules/diagrams/data.mustache', 'utf-8', (err, data) => {
+  TEMPLATES.data = data;
 });
 
 function fetchData(id, cb) {
-    var url = "http://shiny.tinyhost.de/php/getdata.php?time=1&id[]="+id;
-    httpreq.get(url, {binary: true}, function (err, res) {
-        try {
-            cb(res.body.toString().split('\n'));
-        } catch(e) {}
-    });
+  const url = `http://shiny.tinyhost.de/php/getdata.php?time=1&id[]=${id}`;
+  httpreq.get(url, { binary: true }, (err, res) => {
+    try {
+      cb(res.body.toString().split('\n'));
+    } catch (e) {
+      // Swallow Error
+    }
+  });
 }
 
-DATA = {power: '[]', devices: '[]'};
+const DATA = { power: '[]', devices: '[]' };
 
 function handleData(prop, data) {
-    var line,out = []
-    for (var i = 1; i < data.length-1; i++) {
-        line = data[i].split(',');
-        if (line.length === 2) {
-            out.push([ (new Date(line[0])).getTime() , parseFloat(line[1]) ])
-        }
+  let line = [];
+  const out = [];
+  for (let i = 1; i < data.length - 1; i++) {
+    line = data[i].split(',');
+    if (line.length === 2) {
+      out.push([(new Date(line[0])).getTime(), parseFloat(line[1])]);
     }
-    DATA[prop] = JSON.stringify(out);
+  }
+  DATA[prop] = JSON.stringify(out);
 }
 
 function update(cb) {
-    var counter = 0;
-    var next = function () {
-        if (++counter === 2) {
-            cb();
-        }
+  let counter = 0;
+  const next = function() {
+    counter += 1;
+    if (counter === 2) {
+      cb();
     }
-    fetchData(1, function (data) {
-        handleData('power', data);
-        next();
-    }); //power
-    fetchData(4, function (data) {
-        handleData('devices', data);
-        next();
-    }); //devices
+  };
+  fetchData(1, (data) => {
+    handleData('power', data);
+    next();
+  }); //power
+  fetchData(4, (data) => {
+    handleData('devices', data);
+    next();
+  }); //devices
 }
 
-module.exports = function (io) {
-    setInterval(function () {
-        update(function () {
-            io.emit('diagrams.data', Mustache.render(TEMPLATES.data, DATA));
-        });
-    }, 5000);
-    io.on('connect', function (sock) {
-        sock.emit('diagrams', Mustache.render(TEMPLATES.main, {}));
+module.exports = function(io) {
+  setInterval(() => {
+    update(() => {
+      io.emit('diagrams.data', Mustache.render(TEMPLATES.data, DATA));
     });
-}
+  }, 5000);
+  io.on('connect', (sock) => {
+    sock.emit('diagrams', Mustache.render(TEMPLATES.main, {}));
+  });
+};
diff --git a/modules/irc.js b/modules/irc.js
index aa7a050..906503e 100644
--- a/modules/irc.js
+++ b/modules/irc.js
@@ -1,32 +1,41 @@
-var irc = require('irc');
+const irc = require('irc');
 
-var CHANNEL = '#stratum0';
+const CHANNEL = '#stratum0';
 
-var PW = 'Fagee9ie'
+const PW = 'Fagee9ie';
 
-module.exports = function (io) {
-    var client = new irc.Client('bouncer.ksal.de', 'infodisplay', {
-        channels: [CHANNEL],
-        port: 28921,
-        secure: true,
-        selfSigned: true,
-        userName: 'infodisplay/Freenode',
-        password: PW
-    });
-    var content = [];
-    client.addListener('message', function (from, to, message) {
-        if (to != CHANNEL || from === undefined) {return;}
-        message = message.replace(/</g,'&lt;').replace(/>/g,'&gt;');
-        content.push('<p><span>'+from+'</span> '+message+'</p>');
-        if (content.length > 25) {
-            content.shift();
-        }
-        io.emit('irc.inner', content.join(''));
-    });
-    io.on('connect', function (sock) {
-        sock.emit('irc', '<h3>&nbsp;IRC #stratum0</h3><div class="chat" data-infodisplay-outlet="inner"></div>');
-        setTimeout(function () {
-            sock.emit('irc.inner', content.join(''));
-        }, 3000);
-    });
-}
+module.exports = function(io) {
+  const client = new irc.Client('bouncer.ksal.de', 'infodisplay', {
+    channels: [CHANNEL],
+    port: 28921,
+    secure: true,
+    selfSigned: true,
+    userName: 'infodisplay/Freenode',
+    password: PW,
+  });
+  const content = [];
+  client.addListener('message', (from, to, message) => {
+    if (to !== CHANNEL || from === undefined) {
+      return;
+    }
+    // eslint-disable-next-line
+    message = message.replace(/</g, '&lt;').replace(/>/g, '&gt;');
+    content.push(`<p><span>${from}</span> ${message}</p>`);
+    if (content.length > 25) {
+      content.shift();
+    }
+    io.emit('irc.inner', content.join(''));
+  });
+  io.on('connect', sock => {
+    sock.emit(
+      'irc',
+      '<h3>&nbsp;IRC #stratum0</h3><div class="chat" data-infodisplay-outlet="inner"></div>'
+    );
+    setTimeout(
+      () => {
+        sock.emit('irc.inner', content.join(''));
+      },
+      3000
+    );
+  });
+};
diff --git a/modules/weather.js b/modules/weather.js
index b53a4cc..50bd876 100644
--- a/modules/weather.js
+++ b/modules/weather.js
@@ -1,99 +1,93 @@
-var httpreq = require('httpreq');
-var fs = require('fs');
-var Mustache = require('mustache');
+const httpreq = require('httpreq');
+const fs = require('fs');
+const Mustache = require('mustache');
 
 ///CONFIG
-var APPID = "fdc3690e6f9a7572128fe4012b4a2500"
-var CITYID = "2945024"
+const APPID = 'fdc3690e6f9a7572128fe4012b4a2500';
+const CITYID = '2945024';
 
 /// STATICS
-var directions = {NNE:11.25,NE:33.75,ENE:56.25,E:78.75,ESE:101.25,SE:123.75,SSE:146.25,S:168.75,SSW:191.25,SW:213.75,WSW:236.25,W:258.75,WNW:281.25,NW:303.75,NNW:326.25,N:348.75}
-var iconBaseURL = 'http://openweathermap.org/img/w/';
-var TEMPLATE = '';
-fs.readFile('modules/weather/template.mustache', 'utf-8', function (err, data) {
-    TEMPLATE = data;
+const directions = { NNE: 11.25, NE: 33.75, ENE: 56.25, E: 78.75, ESE: 101.25, SE: 123.75, SSE: 146.25, S: 168.75, SSW: 191.25, SW: 213.75, WSW: 236.25, W: 258.75, WNW: 281.25, NW: 303.75, NNW: 326.25, N: 348.75 };
+const iconBaseURL = 'http://openweathermap.org/img/w/';
+let TEMPLATE = '';
+fs.readFile('modules/weather/template.mustache', 'utf-8', (err, data) => {
+  TEMPLATE = data;
 });
 
-function pad(n, width, z) {
-    z = z || '0';
-    n = n + '';
-    return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
-}
-
-function fetchCurrent (cityid, cb) {
-    var url = "http://api.openweathermap.org/data/2.5/weather?units=metric&id="+cityid+"&appid="+APPID;
-    httpreq.get(url, function (err, res) {
-        var dat = JSON.parse(res.body);
-        if (dat.cod) {
-            cb({
-                temp: dat.main.temp,
-                wind: {speed: dat.wind.speed, dir: degToDirection(dat.wind.deg)},
-                pressure: dat.main.pressure,
-                humidity: dat.main.humidity,
-                main: dat.weather[0].main,
-                desc: dat.weather[0].description,
-                icon: iconBaseURL+dat.weather[0].icon+'.png'
-            });
-        }
-    });
+function fetchCurrent(cityid, cb) {
+  const url = `http://api.openweathermap.org/data/2.5/weather?units=metric&id=${cityid}&appid=${APPID}`;
+  httpreq.get(url, (err, res) => {
+    const dat = JSON.parse(res.body);
+    if (dat.cod) {
+      cb({
+        temp: dat.main.temp,
+        wind: { speed: dat.wind.speed, dir: degToDirection(dat.wind.deg) },
+        pressure: dat.main.pressure,
+        humidity: dat.main.humidity,
+        main: dat.weather[0].main,
+        desc: dat.weather[0].description,
+        icon: `${iconBaseURL + dat.weather[0].icon }.png`,
+      });
+    }
+  });
 }
 
-function fetchForecast (cityid, count, cb) {
-    var url = "http://api.openweathermap.org/data/2.5/forecast?units=metric&id="+cityid+"&appid="+APPID;
-    httpreq.get(url, function (err, res) {
-        var raw = JSON.parse(res.body);
-        if (raw.list) {
-            var dat = raw.list.slice(0,count);
-            cb(dat.map(function (d) {
-                var date = new Date(d.dt*1000);
-                return {
-                    time: pad(date.getHours(),2)+':'+pad(date.getMinutes(),2),
-                    temp: d.main.temp,
-                    wind: {speed: d.wind.speed, dir: degToDirection(d.wind.deg)},
-                    main: d.weather[0].main,
-                    desc: d.weather[0].description,
-                    icon: iconBaseURL+d.weather[0].icon+'.png'
-                }
-            }));
-        }
-    });
+function fetchForecast(cityid, count, cb) {
+  const url = `http://api.openweathermap.org/data/2.5/forecast?units=metric&id=${cityid}&appid=${APPID}`;
+  httpreq.get(url, (err, res) => {
+    const raw = JSON.parse(res.body);
+    if (raw.list) {
+      const dat = raw.list.slice(0, count);
+      cb(dat.map((d) => {
+        const date = new Date(d.dt * 1000);
+        return {
+          time: `${pad(date.getHours(), 2)}:${pad(date.getMinutes(), 2)}`,
+          temp: d.main.temp,
+          wind: { speed: d.wind.speed, dir: degToDirection(d.wind.deg) },
+          main: d.weather[0].main,
+          desc: d.weather[0].description,
+          icon: `${iconBaseURL + d.weather[0].icon }.png`,
+        };
+      }));
+    }
+  });
 }
 
 function degToDirection(deg) {
-    var dir = 'N';
-    for (i in directions) {
-        if (deg > directions[i]) {
-            dir = i;
-        }
+  let dir = 'N';
+  for (const i in directions) {
+    if (deg > directions[i]) {
+      dir = i;
     }
-    return dir;
+  }
+  return dir;
 }
 
-module.exports = function (io) {
-    var context = {};
-    var firstTime = true;
-    var update = function (firstUpdateCb) {
-        var then = function () {
-            if (context.current && context.forecast && firstTime) {
-                firstUpdateCb();
-                firstTime = false;
-            }
-        };
-        fetchCurrent(CITYID, function (current) {
-            context.current = current;
-            then();
-        });
-        fetchForecast(CITYID, 6, function (forecast) {
-            context.forecast = forecast;
-            then();
-        });
+module.exports = function(io) {
+  const context = {};
+  let firstTime = true;
+  const update = function(firstUpdateCb) {
+    const then = function() {
+      if (context.current && context.forecast && firstTime) {
+        firstUpdateCb();
+        firstTime = false;
+      }
     };
-    update(function () {
-        var pushToClients = function (sock) {
-            sock.emit('weather', Mustache.render(TEMPLATE, context));
-        };
-        io.on('connect', pushToClients);
-        pushToClients(io);
+    fetchCurrent(CITYID, (current) => {
+      context.current = current;
+      then();
     });
-    setInterval(update, 10*60*1000);
-}
+    fetchForecast(CITYID, 6, (forecast) => {
+      context.forecast = forecast;
+      then();
+    });
+  };
+  update(() => {
+    const pushToClients = function(sock) {
+      sock.emit('weather', Mustache.render(TEMPLATE, context));
+    };
+    io.on('connect', pushToClients);
+    pushToClients(io);
+  });
+  setInterval(update, 10 * 60 * 1000);
+};
diff --git a/package.json b/package.json
index c7faca7..7b188a2 100644
--- a/package.json
+++ b/package.json
@@ -15,8 +15,12 @@
     "socket.io": "^1.3.7",
     "time": "^0.11.4"
   },
-  "devDependencies": {},
+  "devDependencies": {
+    "eslint": "^3.15.0",
+    "eslint-config-marudor": "^4.1.2"
+  },
   "scripts": {
+    "start": "node main.js",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "author": "Kasalehlia",
diff --git a/yarn.lock b/yarn.lock
index 9309e09..421ad92 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9,22 +9,148 @@ accepts@1.3.3, accepts@~1.3.3:
     mime-types "~2.1.11"
     negotiator "0.6.1"
 
+acorn-jsx@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
+  dependencies:
+    acorn "^3.0.4"
+
+acorn@4.0.4:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a"
+
+acorn@^3.0.4:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
+
 after@0.8.2:
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
 
+ajv-keywords@^1.0.0:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
+
+ajv@^4.7.0:
+  version "4.11.3"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.3.tgz#ce30bdb90d1254f762c75af915fb3a63e7183d22"
+  dependencies:
+    co "^4.6.0"
+    json-stable-stringify "^1.0.1"
+
+ansi-escapes@^1.1.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
+
+ansi-regex@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+
+ansi-styles@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+argparse@^1.0.7:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
+  dependencies:
+    sprintf-js "~1.0.2"
+
 array-flatten@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
 
+array-union@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+  dependencies:
+    array-uniq "^1.0.1"
+
+array-uniq@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+
+array.prototype.find@^2.0.1:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.0.3.tgz#08c3ec33e32ec4bab362a2958e686ae92f59271d"
+  dependencies:
+    define-properties "^1.1.2"
+    es-abstract "^1.7.0"
+
 arraybuffer.slice@0.0.6:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca"
 
+arrify@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
+babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
+  dependencies:
+    chalk "^1.1.0"
+    esutils "^2.0.2"
+    js-tokens "^3.0.0"
+
+babel-eslint@^7.1.1:
+  version "7.1.1"
+  resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.1.1.tgz#8a6a884f085aa7060af69cfc77341c2f99370fb2"
+  dependencies:
+    babel-code-frame "^6.16.0"
+    babel-traverse "^6.15.0"
+    babel-types "^6.15.0"
+    babylon "^6.13.0"
+    lodash.pickby "^4.6.0"
+
+babel-messages@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-runtime@^6.22.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
+  dependencies:
+    core-js "^2.4.0"
+    regenerator-runtime "^0.10.0"
+
+babel-traverse@^6.15.0:
+  version "6.23.1"
+  resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48"
+  dependencies:
+    babel-code-frame "^6.22.0"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.22.0"
+    babel-types "^6.23.0"
+    babylon "^6.15.0"
+    debug "^2.2.0"
+    globals "^9.0.0"
+    invariant "^2.2.0"
+    lodash "^4.2.0"
+
+babel-types@^6.15.0, babel-types@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf"
+  dependencies:
+    babel-runtime "^6.22.0"
+    esutils "^2.0.2"
+    lodash "^4.2.0"
+    to-fast-properties "^1.0.1"
+
+babylon@^6.13.0, babylon@^6.15.0:
+  version "6.15.0"
+  resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e"
+
 backo2@1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
 
+balanced-match@^0.4.1:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+
 base64-arraybuffer@0.1.5:
   version "0.1.5"
   resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
@@ -47,10 +173,63 @@ blob@0.0.4:
   version "0.0.4"
   resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921"
 
+brace-expansion@^1.0.0:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9"
+  dependencies:
+    balanced-match "^0.4.1"
+    concat-map "0.0.1"
+
+buffer-shims@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
+
+caller-path@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
+  dependencies:
+    callsites "^0.2.0"
+
 callsite@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
 
+callsites@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
+
+chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+  dependencies:
+    ansi-styles "^2.2.1"
+    escape-string-regexp "^1.0.2"
+    has-ansi "^2.0.0"
+    strip-ansi "^3.0.0"
+    supports-color "^2.0.0"
+
+circular-json@^0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d"
+
+cli-cursor@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
+  dependencies:
+    restore-cursor "^1.0.1"
+
+cli-width@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a"
+
+co@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+
+code-point-at@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+
 component-bind@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
@@ -67,6 +246,18 @@ component-inherit@0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
 
+concat-map@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+concat-stream@^1.4.6:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
+  dependencies:
+    inherits "^2.0.3"
+    readable-stream "^2.2.2"
+    typedarray "^0.0.6"
+
 content-disposition@0.5.2:
   version "0.5.2"
   resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
@@ -83,7 +274,21 @@ cookie@0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
 
-debug@2, debug@2.3.3:
+core-js@^2.4.0:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
+
+core-util-is@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+
+d@^0.1.1, d@~0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309"
+  dependencies:
+    es5-ext "~0.10.2"
+
+debug@2, debug@2.3.3, debug@^2.1.1, debug@^2.2.0:
   version "2.3.3"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c"
   dependencies:
@@ -95,6 +300,29 @@ debug@2.2.0, debug@~2.2.0:
   dependencies:
     ms "0.7.1"
 
+deep-is@~0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+
+define-properties@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
+  dependencies:
+    foreach "^2.0.5"
+    object-keys "^1.0.8"
+
+del@^2.0.2:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
+  dependencies:
+    globby "^5.0.0"
+    is-path-cwd "^1.0.0"
+    is-path-in-cwd "^1.0.0"
+    object-assign "^4.0.1"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+    rimraf "^2.2.8"
+
 depd@~1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
@@ -103,6 +331,13 @@ destroy@~1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
 
+doctrine@^1.2.2:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
+  dependencies:
+    esutils "^2.0.2"
+    isarray "^1.0.0"
+
 ee-first@1.1.1, ee-first@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -150,14 +385,221 @@ engine.io@1.8.3:
     engine.io-parser "1.3.2"
     ws "1.1.2"
 
+es-abstract@^1.7.0:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c"
+  dependencies:
+    es-to-primitive "^1.1.1"
+    function-bind "^1.1.0"
+    is-callable "^1.1.3"
+    is-regex "^1.0.3"
+
+es-to-primitive@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d"
+  dependencies:
+    is-callable "^1.1.1"
+    is-date-object "^1.0.1"
+    is-symbol "^1.0.1"
+
+es5-ext@^0.10.7, es5-ext@^0.10.8, es5-ext@~0.10.11, es5-ext@~0.10.2, es5-ext@~0.10.7:
+  version "0.10.12"
+  resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.12.tgz#aa84641d4db76b62abba5e45fd805ecbab140047"
+  dependencies:
+    es6-iterator "2"
+    es6-symbol "~3.1"
+
+es6-iterator@2:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.0.tgz#bd968567d61635e33c0b80727613c9cb4b096bac"
+  dependencies:
+    d "^0.1.1"
+    es5-ext "^0.10.7"
+    es6-symbol "3"
+
+es6-map@^0.1.3:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.4.tgz#a34b147be224773a4d7da8072794cefa3632b897"
+  dependencies:
+    d "~0.1.1"
+    es5-ext "~0.10.11"
+    es6-iterator "2"
+    es6-set "~0.1.3"
+    es6-symbol "~3.1.0"
+    event-emitter "~0.3.4"
+
+es6-set@~0.1.3:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.4.tgz#9516b6761c2964b92ff479456233a247dc707ce8"
+  dependencies:
+    d "~0.1.1"
+    es5-ext "~0.10.11"
+    es6-iterator "2"
+    es6-symbol "3"
+    event-emitter "~0.3.4"
+
+es6-symbol@3, es6-symbol@~3.1, es6-symbol@~3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.0.tgz#94481c655e7a7cad82eba832d97d5433496d7ffa"
+  dependencies:
+    d "~0.1.1"
+    es5-ext "~0.10.11"
+
+es6-weak-map@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.1.tgz#0d2bbd8827eb5fb4ba8f97fbfea50d43db21ea81"
+  dependencies:
+    d "^0.1.1"
+    es5-ext "^0.10.8"
+    es6-iterator "2"
+    es6-symbol "3"
+
 escape-html@~1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
 
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
+escope@^3.6.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
+  dependencies:
+    es6-map "^0.1.3"
+    es6-weak-map "^2.0.1"
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint-config-marudor@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/eslint-config-marudor/-/eslint-config-marudor-4.1.2.tgz#82761013269f794cb0c5aa275623e1f7bc97280e"
+  dependencies:
+    babel-eslint "^7.1.1"
+    eslint "^3.15.0"
+    eslint-plugin-class-property "^1.0.3"
+    eslint-plugin-flowtype "^2.30.0"
+    eslint-plugin-header "^0.1.0"
+    eslint-plugin-react "^6.9.0"
+    eslint-plugin-sort-imports-es6-autofix "^0.1.1"
+
+eslint-plugin-class-property@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-class-property/-/eslint-plugin-class-property-1.0.3.tgz#aa40b61c8de3e6370669493b640d1949caa5fbdc"
+  dependencies:
+    eslint "^3.13.0"
+    requireindex "~1.1.0"
+
+eslint-plugin-flowtype@^2.30.0:
+  version "2.30.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.30.0.tgz#3054a265f9c8afe3046c3d41b72d32a736f9b4ae"
+  dependencies:
+    lodash "^4.15.0"
+
+eslint-plugin-header@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-header/-/eslint-plugin-header-0.1.0.tgz#bfa0b905e1951035ef51155709f9ad7c535b0bc6"
+
+eslint-plugin-react@^6.9.0:
+  version "6.10.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-6.10.0.tgz#9c48b48d101554b5355413e7c64238abde6ef1ef"
+  dependencies:
+    array.prototype.find "^2.0.1"
+    doctrine "^1.2.2"
+    has "^1.0.1"
+    jsx-ast-utils "^1.3.4"
+    object.assign "^4.0.4"
+
+eslint-plugin-sort-imports-es6-autofix@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-sort-imports-es6-autofix/-/eslint-plugin-sort-imports-es6-autofix-0.1.1.tgz#7b73969f2557b0c6c6259e6c6e8c26761e29d52e"
+  dependencies:
+    eslint "^3.15.0"
+
+eslint@^3.13.0, eslint@^3.15.0:
+  version "3.15.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.15.0.tgz#bdcc6a6c5ffe08160e7b93c066695362a91e30f2"
+  dependencies:
+    babel-code-frame "^6.16.0"
+    chalk "^1.1.3"
+    concat-stream "^1.4.6"
+    debug "^2.1.1"
+    doctrine "^1.2.2"
+    escope "^3.6.0"
+    espree "^3.4.0"
+    estraverse "^4.2.0"
+    esutils "^2.0.2"
+    file-entry-cache "^2.0.0"
+    glob "^7.0.3"
+    globals "^9.14.0"
+    ignore "^3.2.0"
+    imurmurhash "^0.1.4"
+    inquirer "^0.12.0"
+    is-my-json-valid "^2.10.0"
+    is-resolvable "^1.0.0"
+    js-yaml "^3.5.1"
+    json-stable-stringify "^1.0.0"
+    levn "^0.3.0"
+    lodash "^4.0.0"
+    mkdirp "^0.5.0"
+    natural-compare "^1.4.0"
+    optionator "^0.8.2"
+    path-is-inside "^1.0.1"
+    pluralize "^1.2.1"
+    progress "^1.1.8"
+    require-uncached "^1.0.2"
+    shelljs "^0.7.5"
+    strip-bom "^3.0.0"
+    strip-json-comments "~2.0.1"
+    table "^3.7.8"
+    text-table "~0.2.0"
+    user-home "^2.0.0"
+
+espree@^3.4.0:
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.0.tgz#41656fa5628e042878025ef467e78f125cb86e1d"
+  dependencies:
+    acorn "4.0.4"
+    acorn-jsx "^3.0.0"
+
+esprima@^3.1.1:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+
+esrecurse@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220"
+  dependencies:
+    estraverse "~4.1.0"
+    object-assign "^4.0.1"
+
+estraverse@^4.1.1, estraverse@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+
+estraverse@~4.1.0:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2"
+
+esutils@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+
 etag@~1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8"
 
+event-emitter@~0.3.4:
+  version "0.3.4"
+  resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.4.tgz#8d63ddfb4cfe1fae3b32ca265c4c720222080bb5"
+  dependencies:
+    d "~0.1.1"
+    es5-ext "~0.10.7"
+
+exit-hook@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
+
 express@^4.13.3:
   version "4.14.1"
   resolved "https://registry.yarnpkg.com/express/-/express-4.14.1.tgz#646c237f766f148c2120aff073817b9e4d7e0d33"
@@ -189,6 +631,24 @@ express@^4.13.3:
     utils-merge "1.0.0"
     vary "~1.1.0"
 
+fast-levenshtein@~2.0.4:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+
+figures@^1.3.5:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
+  dependencies:
+    escape-string-regexp "^1.0.5"
+    object-assign "^4.1.0"
+
+file-entry-cache@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
+  dependencies:
+    flat-cache "^1.2.1"
+    object-assign "^4.0.1"
+
 finalhandler@0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.5.1.tgz#2c400d8d4530935bc232549c5fa385ec07de6fcd"
@@ -199,6 +659,19 @@ finalhandler@0.5.1:
     statuses "~1.3.1"
     unpipe "~1.0.0"
 
+flat-cache@^1.2.1:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96"
+  dependencies:
+    circular-json "^0.3.1"
+    del "^2.0.2"
+    graceful-fs "^4.1.2"
+    write "^0.2.1"
+
+foreach@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
+
 forwarded@~0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363"
@@ -207,6 +680,60 @@ fresh@0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f"
 
+fs.realpath@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+function-bind@^1.0.2, function-bind@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
+
+generate-function@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
+
+generate-object-property@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
+  dependencies:
+    is-property "^1.0.0"
+
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5:
+  version "7.1.1"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.2"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+globals@^9.0.0, globals@^9.14.0:
+  version "9.16.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-9.16.0.tgz#63e903658171ec2d9f51b1d31de5e2b8dc01fb80"
+
+globby@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
+  dependencies:
+    array-union "^1.0.1"
+    arrify "^1.0.0"
+    glob "^7.0.3"
+    object-assign "^4.0.1"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+graceful-fs@^4.1.2:
+  version "4.1.11"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+
+has-ansi@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+  dependencies:
+    ansi-regex "^2.0.0"
+
 has-binary@0.1.7:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c"
@@ -217,6 +744,12 @@ has-cors@1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
 
+has@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
+  dependencies:
+    function-bind "^1.0.2"
+
 http-errors@~1.5.1:
   version "1.5.1"
   resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750"
@@ -239,14 +772,57 @@ iconv@~2.2.1:
   dependencies:
     nan "^2.3.5"
 
+ignore@^3.2.0:
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.2.tgz#1c51e1ef53bab6ddc15db4d9ac4ec139eceb3410"
+
+imurmurhash@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+
 indexof@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
 
-inherits@2.0.3:
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"
+
+inherits@2, inherits@2.0.3, inherits@^2.0.3, inherits@~2.0.1:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
 
+inquirer@^0.12.0:
+  version "0.12.0"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
+  dependencies:
+    ansi-escapes "^1.1.0"
+    ansi-regex "^2.0.0"
+    chalk "^1.0.0"
+    cli-cursor "^1.0.1"
+    cli-width "^2.0.0"
+    figures "^1.3.5"
+    lodash "^4.3.0"
+    readline2 "^1.0.1"
+    run-async "^0.1.0"
+    rx-lite "^3.1.2"
+    string-width "^1.0.1"
+    strip-ansi "^3.0.0"
+    through "^2.3.6"
+
+interpret@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c"
+
+invariant@^2.2.0:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
+  dependencies:
+    loose-envify "^1.0.0"
+
 ipaddr.js@1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.2.0.tgz#8aba49c9192799585bdd643e0ccb50e8ae777ba4"
@@ -264,14 +840,133 @@ irc@^0.5.2:
     iconv "~2.2.1"
     node-icu-charset-detector "~0.2.0"
 
+is-callable@^1.1.1, is-callable@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
+
+is-date-object@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
+
+is-fullwidth-code-point@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+  dependencies:
+    number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+
+is-my-json-valid@^2.10.0:
+  version "2.15.0"
+  resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b"
+  dependencies:
+    generate-function "^2.0.0"
+    generate-object-property "^1.1.0"
+    jsonpointer "^4.0.0"
+    xtend "^4.0.0"
+
+is-path-cwd@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+
+is-path-in-cwd@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc"
+  dependencies:
+    is-path-inside "^1.0.0"
+
+is-path-inside@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f"
+  dependencies:
+    path-is-inside "^1.0.1"
+
+is-property@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
+
+is-regex@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
+  dependencies:
+    has "^1.0.1"
+
+is-resolvable@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62"
+  dependencies:
+    tryit "^1.0.1"
+
+is-symbol@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572"
+
 isarray@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
 
+isarray@^1.0.0, isarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
+js-tokens@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
+
+js-yaml@^3.5.1:
+  version "3.8.1"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.1.tgz#782ba50200be7b9e5a8537001b7804db3ad02628"
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^3.1.1"
+
+json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
+  dependencies:
+    jsonify "~0.0.0"
+
 json3@3.3.2:
   version "3.3.2"
   resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
 
+jsonify@~0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+
+jsonpointer@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
+
+jsx-ast-utils@^1.3.4:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.0.tgz#5afe38868f56bc8cc7aeaef0100ba8c75bd12591"
+  dependencies:
+    object-assign "^4.1.0"
+
+levn@^0.3.0, levn@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+  dependencies:
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+
+lodash.pickby@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff"
+
+lodash@^4.0.0, lodash@^4.15.0, lodash@^4.2.0, lodash@^4.3.0:
+  version "4.17.4"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+
+loose-envify@^1.0.0:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
+  dependencies:
+    js-tokens "^3.0.0"
+
 media-typer@0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@@ -298,6 +993,22 @@ mime@1.3.4:
   version "1.3.4"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
 
+minimatch@^3.0.2:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
+  dependencies:
+    brace-expansion "^1.0.0"
+
+minimist@0.0.8:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+mkdirp@^0.5.0, mkdirp@^0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+  dependencies:
+    minimist "0.0.8"
+
 ms@0.7.1:
   version "0.7.1"
   resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
@@ -310,10 +1021,18 @@ mustache@^2.2.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0"
 
+mute-stream@0.0.5:
+  version "0.0.5"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
+
 nan@2, nan@^2.3.3, nan@^2.3.5:
   version "2.5.1"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2"
 
+natural-compare@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+
 negotiator@0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
@@ -324,7 +1043,11 @@ node-icu-charset-detector@~0.2.0:
   dependencies:
     nan "^2.3.3"
 
-object-assign@4.1.0:
+number-is-nan@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+
+object-assign@4.1.0, object-assign@^4.0.1, object-assign@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
 
@@ -332,16 +1055,53 @@ object-component@0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
 
+object-keys@^1.0.10, object-keys@^1.0.8:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
+
+object.assign@^4.0.4:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.0.4.tgz#b1c9cc044ef1b9fe63606fc141abbb32e14730cc"
+  dependencies:
+    define-properties "^1.1.2"
+    function-bind "^1.1.0"
+    object-keys "^1.0.10"
+
 on-finished@~2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
   dependencies:
     ee-first "1.1.1"
 
+once@^1.3.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+  dependencies:
+    wrappy "1"
+
+onetime@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
+
+optionator@^0.8.2:
+  version "0.8.2"
+  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
+  dependencies:
+    deep-is "~0.1.3"
+    fast-levenshtein "~2.0.4"
+    levn "~0.3.0"
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+    wordwrap "~1.0.0"
+
 options@>=0.0.5:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f"
 
+os-homedir@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+
 parsejson@0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab"
@@ -364,14 +1124,52 @@ parseurl@~1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
 
+path-is-absolute@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+
+path-is-inside@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+
 path-to-regexp@0.1.7:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
 
+pify@^2.0.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+
+pinkie-promise@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+  dependencies:
+    pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+
 pixl-xml@^1.0.4:
   version "1.0.10"
   resolved "https://registry.yarnpkg.com/pixl-xml/-/pixl-xml-1.0.10.tgz#aedc1a47d8b16b9a71d9dad9f51332163f7a70ee"
 
+pluralize@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
+
+prelude-ls@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+
+process-nextick-args@~1.0.6:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
+
+progress@^1.1.8:
+  version "1.1.8"
+  resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
+
 proxy-addr@~1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.3.tgz#dc97502f5722e888467b3fa2297a7b1ff47df074"
@@ -387,6 +1185,78 @@ range-parser@~1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
 
+readable-stream@^2.2.2:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e"
+  dependencies:
+    buffer-shims "^1.0.0"
+    core-util-is "~1.0.0"
+    inherits "~2.0.1"
+    isarray "~1.0.0"
+    process-nextick-args "~1.0.6"
+    string_decoder "~0.10.x"
+    util-deprecate "~1.0.1"
+
+readline2@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
+  dependencies:
+    code-point-at "^1.0.0"
+    is-fullwidth-code-point "^1.0.0"
+    mute-stream "0.0.5"
+
+rechoir@^0.6.2:
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
+  dependencies:
+    resolve "^1.1.6"
+
+regenerator-runtime@^0.10.0:
+  version "0.10.3"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e"
+
+require-uncached@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
+  dependencies:
+    caller-path "^0.1.0"
+    resolve-from "^1.0.0"
+
+requireindex@~1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162"
+
+resolve-from@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
+
+resolve@^1.1.6:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.2.0.tgz#9589c3f2f6149d1417a40becc1663db6ec6bc26c"
+
+restore-cursor@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
+  dependencies:
+    exit-hook "^1.0.0"
+    onetime "^1.0.0"
+
+rimraf@^2.2.8:
+  version "2.5.4"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
+  dependencies:
+    glob "^7.0.5"
+
+run-async@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
+  dependencies:
+    once "^1.3.0"
+
+rx-lite@^3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
+
 send@0.14.2:
   version "0.14.2"
   resolved "https://registry.yarnpkg.com/send/-/send-0.14.2.tgz#39b0438b3f510be5dc6f667a11f71689368cdeef"
@@ -418,6 +1288,18 @@ setprototypeof@1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08"
 
+shelljs@^0.7.5:
+  version "0.7.6"
+  resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad"
+  dependencies:
+    glob "^7.0.0"
+    interpret "^1.0.0"
+    rechoir "^0.6.2"
+
+slice-ansi@0.0.4:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
+
 socket.io-adapter@0.5.0:
   version "0.5.0"
   resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b"
@@ -462,10 +1344,70 @@ socket.io@^1.3.7:
     socket.io-client "1.7.3"
     socket.io-parser "2.3.1"
 
+sprintf-js@~1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+
 "statuses@>= 1.3.1 < 2", statuses@~1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
 
+string-width@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+  dependencies:
+    code-point-at "^1.0.0"
+    is-fullwidth-code-point "^1.0.0"
+    strip-ansi "^3.0.0"
+
+string-width@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e"
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^3.0.0"
+
+string_decoder@~0.10.x:
+  version "0.10.31"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+
+strip-ansi@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+  dependencies:
+    ansi-regex "^2.0.0"
+
+strip-bom@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+
+strip-json-comments@~2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+
+supports-color@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+table@^3.7.8:
+  version "3.8.3"
+  resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
+  dependencies:
+    ajv "^4.7.0"
+    ajv-keywords "^1.0.0"
+    chalk "^1.1.1"
+    lodash "^4.0.0"
+    slice-ansi "0.0.4"
+    string-width "^2.0.0"
+
+text-table@~0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+
+through@^2.3.6:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+
 time@^0.11.4:
   version "0.11.4"
   resolved "https://registry.yarnpkg.com/time/-/time-0.11.4.tgz#ec3c8947d7fa488f3b1978b8110a68186f5d340f"
@@ -478,6 +1420,20 @@ to-array@0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
 
+to-fast-properties@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320"
+
+tryit@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
+
+type-check@~0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+  dependencies:
+    prelude-ls "~1.1.2"
+
 type-is@~1.6.14:
   version "1.6.14"
   resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.14.tgz#e219639c17ded1ca0789092dd54a03826b817cb2"
@@ -485,6 +1441,10 @@ type-is@~1.6.14:
     media-typer "0.3.0"
     mime-types "~2.1.13"
 
+typedarray@^0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+
 ultron@1.0.x:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa"
@@ -493,6 +1453,16 @@ unpipe@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
 
+user-home@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
+  dependencies:
+    os-homedir "^1.0.0"
+
+util-deprecate@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+
 utils-merge@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
@@ -501,6 +1471,20 @@ vary@~1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.0.tgz#e1e5affbbd16ae768dd2674394b9ad3022653140"
 
+wordwrap@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+
+wrappy@1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+write@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
+  dependencies:
+    mkdirp "^0.5.1"
+
 ws@1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f"
@@ -516,6 +1500,10 @@ xmlhttprequest-ssl@1.5.3:
   version "1.5.3"
   resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d"
 
+xtend@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+
 yeast@0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
-- 
GitLab