diff --git a/.eslintrc.json b/.eslintrc.json
index ed55f719b7e472b089b05b9ae0c2b6eefe4e735f..6bc9af7e5870290ce9b10f5a7677cbd40d9db172 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -7,6 +7,7 @@
     "parserOptions": {
         "sourceType": "module"
     },
+    "parser": "babel-eslint",
     "rules": {
         "no-unused-vars": 0,
         "indent": ["error",4],
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c5c956f4b285c701b0cb02ecd4b4607a1fee55e1..ffceb2fe5766f9ebf3d9e22831f3c524732f63ad 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -14,6 +14,7 @@ cache:
   - ldap_connexion_config.json
 
 stages:
+  - install
   - build
   - test
   - deploy
@@ -25,19 +26,17 @@ stages:
 build:
   stage: build
   script:
-    - npm install -q
+    - npm install -qy
     - npm run build
     - knex migrate:latest
     - knex seed:run
   artifacts:
     paths:
-      - ldap_connexion_config.json
-      - build/
       - node_modules/
-    expire_in: 240   min
+      - build/
   tags:
-    - database
     - build
+    - database
 
 # Run ESLint to analyse our JS code
 test:lint:
@@ -47,14 +46,22 @@ test:lint:
   tags:
     - lint
 
-deploy_staging:
+deploy-staging:
   stage: deploy
+  only:
+    - master
+  before_script:
+    - eval $(ssh-agent -s)
+    - ssh-add <(echo "$STAGING_PRIVATE_KEY")
+    - mkdir -p ~/.ssh
+    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
   script:
     - npm run build
-    - mkdir -p /opt/sigma-back-dev
-    - cp -r build/ /opt/sigma-back-dev/build/
+    - ssh -p22 sigma-dev@roued "mkdir -p /opt/sigma-back-dev"
+    - ssh -p22 sigma-dev@roued "rm -rf /opt/sigma-back-dev/build"
+    - scp -p22 -r build/ sigma-dev@roued:/opt/sigma-back-dev/build
   environment:
     name: staging
     url: http://129.104.210.10:3000
   tags:
-    - deployment
\ No newline at end of file
+    - deploy
\ No newline at end of file
diff --git a/db/migrations/20180303192411_create_metaGroups.js b/db/migrations/20180303192411_create_metaGroups.js
new file mode 100644
index 0000000000000000000000000000000000000000..90df1a877c7fe944429a21ce190b856bb0ac3cfd
--- /dev/null
+++ b/db/migrations/20180303192411_create_metaGroups.js
@@ -0,0 +1,49 @@
+
+/* 
+Une mutation pour rajouter dans la BDD les types SimpleGroup et MetaGroup 
+(cf la documentation de l'interface GraphQL)
+Les objets qui étaient jusqu''à présent stoqués dans la table groups 
+sont déplacés dans la table simple_groups
+En cas de rollback, le déplacement se fait dans l'autre sens
+(et les meta groupes sont perdus)
+
+Après cette mutation, plus rien n'est sensé être mis directement dans la table groups
+*/
+
+exports.up = function(knex, Promise) {
+    return knex('groups').select().then( groups_content => {
+        return knex('groups').del().then(function () {
+            return knex.schema.table('groups', function (table){
+                table.dropColumn('school');
+                table.dropColumn('parentuid');
+            }).then(()=> {
+                return knex.schema.createTable('simple_groups', function (table){
+                    table.inherits('groups');
+                    table.string('parentuid');
+                    table.enum('school', ['polytechnique', 'ensta', 'supoptique']).notNullable();
+                }).then(() => {
+                    return knex.schema.createTable('meta_groups', function (table){
+                        table.inherits('groups');
+                    }).then(function(){
+                        return knex('simple_groups').insert(groups_content);
+                    });
+                });
+            });
+        });
+    });
+};
+
+exports.down = function(knex, Promise) {
+    return knex('simple_groups').select().then(simple_groups_content => {
+        return knex.schema.dropTable('simple_groups').then(function (){
+            return knex.schema.dropTable('meta_groups').then(function (){
+                return knex.schema.table('groups', function (table){
+                    table.string('parentuid');
+                    table.enum('school', ['polytechnique', 'ensta', 'supoptique']).notNullable();
+                }).then(function (){
+                    return knex('groups').insert(simple_groups_content);
+                });
+            });
+        });
+    });
+};
diff --git a/db/migrations/20180304154225_group_type_column.js b/db/migrations/20180304154225_group_type_column.js
new file mode 100644
index 0000000000000000000000000000000000000000..f178a0a9ddf63ec1de5e2e6e050eb5ab4ea6af1c
--- /dev/null
+++ b/db/migrations/20180304154225_group_type_column.js
@@ -0,0 +1,17 @@
+
+exports.up = function(knex, Promise) {
+    return knex.schema.table('groups', function(table) {
+        table.enum('type', ['simple', 'meta', 'error']).notNullable().defaultTo('error');
+    }).then( () => {
+        return knex('simple_groups').update({type : "simple"}).then(() => {
+            return knex('meta_groups').update({type : "meta"});
+        });
+    });
+  
+};
+
+exports.down = function(knex, Promise) {
+    return knex.schema.table('groups', function(table) {
+        table.dropColumn('type');
+    });
+};
diff --git a/db/migrations/20180305111321_metaGroup_member_table.js b/db/migrations/20180305111321_metaGroup_member_table.js
new file mode 100644
index 0000000000000000000000000000000000000000..ab7268d3ee913ab518f8be69170f7c9006893411
--- /dev/null
+++ b/db/migrations/20180305111321_metaGroup_member_table.js
@@ -0,0 +1,13 @@
+
+exports.up = function(knex, Promise) {
+  return knex.schema.createTable('meta_group_membership', function (table){
+    table.timestamp(true, true);
+    table.string('member_uid').notNullable();
+    table.string('union_uid').notNullable();
+    table.enum('status', ['admin', 'speaker', 'basic']).notNullable();
+  });
+};
+
+exports.down = function(knex, Promise) {
+  return knex.schema.dropTable('meta_group_membership');
+};
diff --git a/db/migrations/20180307213043_fixes_and_messages.js b/db/migrations/20180307213043_fixes_and_messages.js
new file mode 100644
index 0000000000000000000000000000000000000000..7c46a723b9ad3ae6efb4f501eb215e97dd1b0488
--- /dev/null
+++ b/db/migrations/20180307213043_fixes_and_messages.js
@@ -0,0 +1,44 @@
+
+exports.up = async function(knex, Promise) {
+    await knex.schema.renameTable("posts", "messages");
+    await knex.schema.table('messages', function(table){
+        table.renameColumn('description', 'content');
+    });
+    await knex.schema.createTable('announcements', function (table){
+        table.inherits('messages');
+    });
+    await knex.schema.createTable('events', function (table){
+        table.inherits('messages');
+        table.string('location');
+        table.dateTime('start_time');
+        table.dateTime('end_time');
+        table.boolean('is_announcement');
+    });
+    await knex.schema.createTable('group_message_relationships', function(table){
+        table.integer('message').notNullable();
+        table.string('group').notNullable();
+        table.enum('status', ['join', 'host', 'publish']).notNullable();
+    });
+    await knex.schema.createTable('user_participation', function(table){
+        table.integer('event').notNullable();
+        table.string('user_uid').notNullable();
+        table.enum('user_db', ['ldap']).notNullable().defaultTo('ldap');
+    });
+    return;
+};
+
+exports.down = async function(knex, Promise) {
+    await knex.schema.dropTable('group_message_relationships');
+    await knex.schema.dropTable('user_participation');
+    let event_posts = await knex.select().from('events');
+    let announcment_posts = await knex.select().from('announcements');
+    await knex.schema.dropTable('events');
+    await knex.schema.dropTable('announcements');
+    await knex.schema.renameTable('messages', 'posts');
+    await knex.schema.table('posts', function(table){
+        table.renameColumn('content', 'description');
+    });
+    await knex('messages').insert(event_posts);
+    await knex('messages').insert(announcment_posts);
+    return;
+};
diff --git a/db/migrations/20180309145434_supervision.js b/db/migrations/20180309145434_supervision.js
new file mode 100644
index 0000000000000000000000000000000000000000..d7ffa96ec1a2cb75c5573aee3d81bb79f71bf22a
--- /dev/null
+++ b/db/migrations/20180309145434_supervision.js
@@ -0,0 +1,14 @@
+
+exports.up = function(knex, Promise) {
+    return knex.schema.createTable('taken_rights', function(table){
+        table.timestamp(true, true);
+        table.string('user_uid').notNullable();
+        table.string('group_uid').notNullable();
+        table.string('justification');
+    });
+  
+};
+
+exports.down = function(knex, Promise) {
+  return knex.schema.dropTable('taken_rights');
+};
diff --git a/db/seeds/01_create_groups.js b/db/seeds/01_create_groups.js
index 1eb823722ccc15ba7e2b75ae5dda990b632c4a71..2b00624e6e0e89ca45f467c41887dd104444bb4f 100644
--- a/db/seeds/01_create_groups.js
+++ b/db/seeds/01_create_groups.js
@@ -3,44 +3,92 @@ exports.seed = function(knex, Promise) {
   // Deletes ALL existing entries
   return knex('groups').del()
     .then(function () {
+    knex('simple_groups').del()
+    .then(function() {
       // Inserts seed entries
-      const groups = [{
+      const simple_groups = [{
           name: 'BR',
           uid: 'br',
           website: 'br.binets.fr',
           description: 'Le Binet Réseau est responsable du réseau internet des élèves sur le campus de l\'Ecole polytechnique.',
           school: 'polytechnique',
-          parentuid: 'kes'
+          parentuid: 'kes',
+          type : 'simple'
         },{
           name: 'JTX',
           uid: 'jtx',
           website: 'binet-jtx.com',
           school: 'polytechnique',
-          parentuid: 'kes'
+          parentuid: 'kes',
+          type : 'simple'
+        },{
+          name: 'Faërix',
+          uid: 'faerix',
+          website: 'faerix.net',
+          school: 'polytechnique',
+          parentuid: 'kes',
+          type : 'simple'
+        },{
+          name: 'Bôbar',
+          uid: 'bob',
+          description : "Viens. On est bien",
+          website: 'bôbar.binet.fr',
+          school: 'polytechnique',
+          parentuid: 'kes',
+          type : 'simple'
         },{
           name: 'Kès',
           uid: 'kes',
           website: 'kes.binets.fr',
-          school: 'polytechnique'
+          school: 'polytechnique',
+          type : 'simple'
         },{
           name: 'DaTA',
           uid: 'data',
           website: 'data-ensta.fr',
           school: 'ensta',
-          parentuid: 'bdeensta'
+          parentuid: 'bdeensta',
+          type : 'simple'
         },{
           name: 'Laser Wave',
           uid: 'laserwave',
           website: 'laserwave.fr',
-          school: 'supoptique'
+          school: 'supoptique',
+          type : 'simple'
+        },
+        {
+          name: 'WikiX',
+          uid: 'wikix',
+          website: 'https://wikix.polytechnique.org/',
+          school: "polytechnique",
+          description: "Le recueil de la mémoire des élèves",
+          type: "simple",
         },{
           name: 'BDE Ensta',
           uid: 'bdeensta',
           website: 'http://bde.ensta-paristech.fr/',
-          school: 'ensta'
-        }
+          school: 'ensta',
+          type : 'simple'
+        },
+        {
+          name: "X-Chine",
+          uid: "x-chine",
+          website: "",
+          school: "polytechnique",
+          description: `X-Chine est le binet qui rassemble les amoureux et les curieux de l'Empire du Milieu, qu'ils soient chinois ou non !`,
+          type: "simple"
+        },
+        {
+          name: 'Subaïsse',
+          uid: 'subaisse',
+          description: 'Le Binet de ceux qui subissent',
+          school: 'polytechnique',
+          parentuid: 'kes',
+          type : 'simple'
+      },
       ];
 
-      return knex('groups').insert(groups);
+      return knex('simple_groups').insert(simple_groups);
     });
+  });
 };
diff --git a/db/seeds/02_make_posts.js b/db/seeds/02_make_posts.js
index 4b9f5776532838d1e0a6f80dff23d2717227079c..039ff10f6f910e8111d3a621e46d1c0da5767bfc 100644
--- a/db/seeds/02_make_posts.js
+++ b/db/seeds/02_make_posts.js
@@ -1,6 +1,7 @@
 
 exports.seed = function(knex, Promise) {
   // Deletes ALL existing entries
+  /*
   return knex('posts').del()
     .then(function () {
       const posts = [{
@@ -11,8 +12,17 @@ exports.seed = function(knex, Promise) {
         title: "Proj'et Promotion",
         description: "La nouvelle proj' du JTX arrive !",
         authors: ['br']
+      },{
+        title: "Fête de la Lune",
+        description: "C'est bientôt la fête de la Lune ! Inscrivez-vous pour un dîner-spectacle dans le Grand Hall !",
+        authors: ['x-chine']
+      },{
+        title: "Formation Web",
+        description: "Envie d'apprendre à faire un site Web en Django ? Alors viens en amphi Sauvy ce jeudi à 20h !",
+        authors: ['br']
       }];
 
       return knex('posts').insert(posts);
     });
+    */
 };
diff --git a/db/seeds/03_make_requests.js b/db/seeds/03_make_requests.js
index 2cb07fa44bcd80687b11bacb6099acb4d5c2b87e..aceaf4721893cb157cd6d5197384e49ff99b0e36 100644
--- a/db/seeds/03_make_requests.js
+++ b/db/seeds/03_make_requests.js
@@ -2,19 +2,37 @@
 exports.seed = function(knex, Promise) {
   // Deletes ALL existing entries
   return knex('user_join_group').del()
-    .then(function () {
-      // Inserts seed entries
-      return knex('user_join_group').insert([
-        { id: 1, 
-          recipient: 'br',
-          message: "C'est ici pour développer sigma ?",
-          useruid: "anatole.romon"
-        },
-        { id: 2, 
-          recipient: 'br',
-          message: "Bonjour, je cherche le binet subaisse",
-          useruid: "quentin.gendre"
-        }
-      ]);
-    });
+  .then(function () {
+    // Inserts seed entries
+  return knex('user_join_group').insert([
+    { id: 1, 
+      recipient: 'br',
+      message: "C'est ici pour développer sigma ?",
+      useruid: "anatole.romon"
+    },
+    { id: 2, 
+      recipient: 'br',
+      message: "Bonjour, je cherche le binet subaisse",
+      useruid: "quentin.gendre"
+    },
+    {id : 3,
+    recipient: 'jtx',
+    message: "Quand je serais grand je serais cinéaste !",
+    useruid: "anatole.romon"
+  }
+  ]).then(() => {
+  return knex('group_join_event').del()
+  .then(function (){
+  return knex('group_join_event').insert([
+    {
+      id : 4,
+      recipient : "br",
+      message : "nous aussi on veut coder sigma",
+      eventuid : 42,
+      senderuid : "subaisse"
+    }
+  ]);
+  });
+  });
+  });
 };
diff --git a/db/seeds/04_make_metagroups.js b/db/seeds/04_make_metagroups.js
new file mode 100644
index 0000000000000000000000000000000000000000..432bb33d1b96b6f4fda099d16cbf35d471193c6a
--- /dev/null
+++ b/db/seeds/04_make_metagroups.js
@@ -0,0 +1,24 @@
+
+exports.seed = function(knex, Promise) {
+    // Deletes ALL existing entries
+    return knex('meta_groups').del()
+      .then(function () {
+        // Inserts seed entries
+        return knex('meta_groups').insert([
+          { 
+            name: 'Fédérez',
+            uid: 'federez',
+            website: 'federez.io',
+            description: "L'association de toutes les associations de réseau des écoles",
+            type : 'meta'
+          },
+          { 
+            name: 'BSCkBl',
+            uid: 'bsckbl',
+            website: 'bsckbl.binets.fr',
+            type : 'meta'
+          }
+        ]);
+      });
+  };
+  
\ No newline at end of file
diff --git a/db/seeds/05_metagroup_membership.js b/db/seeds/05_metagroup_membership.js
new file mode 100644
index 0000000000000000000000000000000000000000..cd1587503a14bf8f86f50d8f3964f34113bae412
--- /dev/null
+++ b/db/seeds/05_metagroup_membership.js
@@ -0,0 +1,23 @@
+
+exports.seed = async function(knex, Promise) {
+    // Deletes ALL existing entries
+    await knex('meta_groups').del();
+    await knex('meta_group_membership').insert([
+      { 
+        member_uid : "br",
+        union_uid : "federez",
+        status : "admin"
+      },
+      { 
+        member_uid : "data",
+        union_uid : "federez",
+        status : "admin"
+      },
+      { 
+        member_uid : "bob",
+        union_uid : "bsckbl",
+        status : "admin"
+      }
+    ]);
+    return;
+};
diff --git a/db/seeds/06_taken_rights.js b/db/seeds/06_taken_rights.js
new file mode 100644
index 0000000000000000000000000000000000000000..9915ef9ae4d45a7f55c737c185ed4589313b9258
--- /dev/null
+++ b/db/seeds/06_taken_rights.js
@@ -0,0 +1,14 @@
+
+exports.seed = function(knex, Promise) {
+  // Deletes ALL existing entries
+  return knex('taken_rights').del()
+    .then(function () {
+      // Inserts seed entries
+      return knex('taken_rights').insert([
+        {
+          user_uid : "anatole.romon",
+          group_uid : "kes",
+        }
+      ]);
+    });
+};
diff --git a/db/seeds/07_make_event.js b/db/seeds/07_make_event.js
new file mode 100644
index 0000000000000000000000000000000000000000..f0439c85dca44179a5ce869bf0d0df4834d67bb5
--- /dev/null
+++ b/db/seeds/07_make_event.js
@@ -0,0 +1,19 @@
+
+exports.seed = function(knex, Promise) {
+  // Deletes ALL existing entries
+  return knex('events').del()
+    .then(function () {
+      // Inserts seed entries
+      return knex('events').insert([
+        {
+          id : 42,
+          title : "coder sigma",
+          content : "Tous ensemble pour faire du Dev. Que demander de plus ? (a part du sommeil)",
+          start_time : knex.fn.now(),
+          end_time : knex.fn.now(),
+          authors : [],
+          is_announcement : false
+        }
+      ]);
+    });
+};
diff --git a/knexfile.js b/knexfile.js
index 70b1ff709561dd50ca16efabf56d785fc7e6d94c..4b48dc940c31400be70e9d36b47b8c7258b4f452 100644
--- a/knexfile.js
+++ b/knexfile.js
@@ -29,5 +29,26 @@ module.exports = {
         seeds: {
             directory: path.resolve('./db/seeds')
         }
+    },
+    production: {
+        client: 'pg',
+        connection: {
+            host: 'localhost',
+            user: 'will',
+            password: 'password',
+            database: 'sigma_dev',
+            charset: 'utf8'
+        },
+        pool: {
+            min: 2,
+            max: 10
+        },
+        migrations: {
+            tableName: 'knex_migrations',
+            directory: path.resolve('./db/migrations')
+        },
+        seeds: {
+            directory: path.resolve('./db/seeds')
+        }
     }
 };
diff --git a/ldap_config.json b/ldap_config.json
index 1e20d240cd3d988ff22b7aae9c35a19ab8f27383..f19e61a42b4b6ebcde0d7a86a60054e8b3ba9045 100644
--- a/ldap_config.json
+++ b/ldap_config.json
@@ -1,80 +1,75 @@
 {
+	"COMMENT1": "Partie utilisée par ldap_auth",
 	"ldap": {
 		"server": "ldap://frankiz.eleves.polytechnique.fr:389",
 		"searchBase": "ou=eleves,dc=frankiz,dc=net",
 		"searchFilter": "(uid={{username}})"
 	},
+	
+	"COMMENT2": "Noms de domaines dans LDAP ; le niv d'après est en uid=, voir Wikipedia",
 	"dn_groups":"ou=groups,dc=frankiz,dc=net",
 	"dn_users": "ou=eleves,dc=frankiz,dc=net",
+
 	"key_id": "uid",
-	"lg": {
-		"filtre": "(uid=${id})",
-		"attributs": "brMemberOf"
+	"user": {
+		"direct_input": ["givenName","lastName","birthdate", "promotion", "mail","phone","photo","adress"],
+		"multiple_input": ["ips","forlifes"],
+		"profil": ["jpegPhoto","displayName","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP","brMemberOf","brNewsReadAccess","brNewsPostAccess","brAlias"],
+		"photo": "jpegPhoto",
+		"givenName": "givenName",
+		"lastName": "sn",
+		"nickname": "displayName",
+		"birthdate": "brBirthdate",
+		"nationality": "country",
+		"promotion": "brPromo",
+		"phone": "telephoneNumber",
+		"mail": "mail",
+		"adress": "brRoom",
+		"ips": "brIP",
+		"id": "uidNumber",
+		"sport": "brMemberOf",
+		"password": "userPassword",
+		"forlifes": "brAlias",
+		"idNum": "gidNumber",
+		"directory": "homeDirectory",
+		"readPerm": "brNewsReadAccess",
+		"writePerm": "brNewsPostAccess",
+		"fullName": "cn",
+		"login": "loginShell",
+		"groups": "brMemberOf",
+		"school": "brMemberOf",
+		"studies": "brMemberOf",
+		"cleanFullName": "gecos",
+		"class": "objectClass"
 	},
-	"lm": {
-		"filtre": "(uid=${id})",
-		"attributs": "restrictedMemberUid"
+	"group": {
+		"direct_input": ["name","ns"],
+		"profil": ["cn","restrictedMemberUid","memberUid", "brNS"],
+		"name": "cn",
+		"member": "restrictedMemberUid",
+		"admin": "memberUid",
+		"type": "brNS",
+		"idNumber": "uidNumber",
+		"idNumber2": "gidNumber",
+		"password": "userPassword",
+		"login": "loginShell",
+		"directory": "homeDirectory",
+		"cleanFullName": "gecos",
+		"readPerm": "brNewsReadAccess",
+		"writePerm": "brNewsPostAccess"
 	},
-	"la": {
-		"filtre": "(uid=${id})",
-		"attributs": "memberUid"
-	},
-	"rs": {
-		"filtre": "(uid=${id})",
-		"attributs": ["jpegPhoto","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP","brMemberOf"]
+	"am": {
+		"key_gr": "restrictedMemberUid",
+		"key_u": "brMemberOf"
 	},
-	"tgty": {
-		"filtre": "(brNS=${ty})",
-		"types": ["binet", "free"]
+	"aa": {
+		"key_gr": "memberUid"
 	},
-	"tolm": {
-		"input_names": ["givenName", "lastName", "nickname", "nationality", "promotion", "phone", "adress", "ip", "school", "groups","studies","sport","mail"],
-		"correspondance": {
-			"givenName": "givenName",
-			"lastName": "sn",
-			"nickname": "displayName",
-			"nationality": "country",
-			"promotion": "brPromo",
-			"phone": "telephoneNumber",
-			"mail": "mail",
-			"adress": "brRoom",
-			"ip": "brIP", 
-			"school": "brMemberOf", "groups": "brMemberOf", "studies": "brMemberOf", "sport": "brMemberOf"
-		}
+	"sm": {
+		"attributs": ["restrictedMemberUid", "brMemberOf"]
 	},
-	"tol": {
-		"attributes": ["jpegPhoto","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP","brMemberOf"]
-	},
-	"cru": {
-		"single_user_infos": ["uid","givenName","sn","displayName", "brBirthdate", "uidNumber","gidNumber", "homeDirectory", "userPassword","brPromo","brMemberOf","loginShell","email","telephoneNumber","jpegPhoto","brRoom","brNewsReadAccess","brNewsPostAccess","brAlias","brIP","cn","gecos"],
-		"expr_single_values_user": {
-			"uid": "data['hruid'];",
-			"givenName": "data['first_name'];",
-			"sn": "data['last_name'];",
-			"displayName": "data['nickname'];",
-			"brBirthdate": "data['birthdate'];",
-			"uidNumber": "(2*data['uid']+10000).toString();",
-			"gidNumber": "5000.toString();",
-			"homeDirectory": "'/hosting/users/' + data['hruid'];",
-			"userPassword": "data['password'];",
-			"brPromo": "data['promo'];",
-			"loginShell": "if (data['on_platal']==true) {'/bin/bash'; } else { '/sbin/nologin'; }",
-			"email": "data['email'];",
-			"telephoneNumber":"data['phone'];",
-			"jpegPhoto": "data['photo'];",
-			"brRoom": "data['room'];",
-			"brNewsReadAccess": "if (data['read_perm'].length>0) { 'br.*,public.*'; } else { 'br.*,public.*,'+data['read_perm']; }",
-			"brNewsPostAccess": "if (data['write_perm'].length>0) { 'br.*,!br.blague-du-jour,public.*,!br.campagnekes'; } else { 'br.*,!br.blague-du-jour,public.*,!br.campagnekes,'+data['read_perm']; }",
-			"brAlias": "data['forlifes'].split(' ');",
-			"brIP": "data['ips'].split(',');",
-			"cn": "data['first_name']+' '+data['last_name'].toUpperCase();",
-			"gecos": "btoa(data['first_name']+' '+data['last_name'].toUpperCase());"
-		},
-		"multiple_user_infos": ["objectClass", "brMemberOf"],
-		"expr_multiple_values_user": {
-			"objectClass": "['posixAccount', 'shadowAccount', 'inetOrgPerson', 'brAccount']",
-			"brMemberOf": "data['groups']"
-		}
+	"sa": {
+		"attributs": "memberUid"
 	},
 	"sessionSecret":"change this"
 }
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 9f6530332ce026f63a160fc68c6b313652085a24..9dbe1464728c8f33a21b25a36cd159e8c81aaf9b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,6 +4,91 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.40.tgz",
+      "integrity": "sha512-eVXQSbu/RimU6OKcK2/gDJVTFcxXJI4sHbIqw2mhwMZeQ2as/8AhS9DGkEDoHMBBNJZ5B0US63lF56x+KDcxiA==",
+      "requires": {
+        "@babel/highlight": "7.0.0-beta.40"
+      }
+    },
+    "@babel/generator": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.40.tgz",
+      "integrity": "sha512-c91BQcXyTq/5aFV4afgOionxZS1dxWt8OghEx5Q52SKssdGRFSiMKnk9tGkev1pYULPJBqjSDZU2Pcuc58ffZw==",
+      "requires": {
+        "@babel/types": "7.0.0-beta.40",
+        "jsesc": "2.5.1",
+        "lodash": "4.17.5",
+        "source-map": "0.5.7",
+        "trim-right": "1.0.1"
+      }
+    },
+    "@babel/helper-function-name": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.40.tgz",
+      "integrity": "sha512-cK9BVLtOfisSISTTHXKGvBc2OBh65tjEk4PgXhsSnnH0i8RP2v+5RCxoSlh2y/i+l2fxQqKqv++Qo5RMiwmRCA==",
+      "requires": {
+        "@babel/helper-get-function-arity": "7.0.0-beta.40",
+        "@babel/template": "7.0.0-beta.40",
+        "@babel/types": "7.0.0-beta.40"
+      }
+    },
+    "@babel/helper-get-function-arity": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.40.tgz",
+      "integrity": "sha512-MwquaPznI4cUoZEgHC/XGkddOXtqKqD4DvZDOyJK2LR9Qi6TbMbAhc6IaFoRX7CRTFCmtGeu8gdXW2dBotBBTA==",
+      "requires": {
+        "@babel/types": "7.0.0-beta.40"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.40.tgz",
+      "integrity": "sha512-mOhhTrzieV6VO7odgzFGFapiwRK0ei8RZRhfzHhb6cpX3QM8XXuCLXWjN8qBB7JReDdUR80V3LFfFrGUYevhNg==",
+      "requires": {
+        "chalk": "2.3.2",
+        "esutils": "2.0.2",
+        "js-tokens": "3.0.2"
+      }
+    },
+    "@babel/template": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.40.tgz",
+      "integrity": "sha512-RlQiVB7eL7fxsKN6JvnCCwEwEL28CBYalXSgWWULuFlEHjtMoXBqQanSie3bNyhrANJx67sb+Sd/vuGivoMwLQ==",
+      "requires": {
+        "@babel/code-frame": "7.0.0-beta.40",
+        "@babel/types": "7.0.0-beta.40",
+        "babylon": "7.0.0-beta.40",
+        "lodash": "4.17.5"
+      }
+    },
+    "@babel/traverse": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.40.tgz",
+      "integrity": "sha512-h96SQorjvdSuxQ6hHFIuAa3oxnad1TA5bU1Zz88+XqzwmM5QM0/k2D+heXGGy/76gT5ajl7xYLKGiPA/KTyVhQ==",
+      "requires": {
+        "@babel/code-frame": "7.0.0-beta.40",
+        "@babel/generator": "7.0.0-beta.40",
+        "@babel/helper-function-name": "7.0.0-beta.40",
+        "@babel/types": "7.0.0-beta.40",
+        "babylon": "7.0.0-beta.40",
+        "debug": "3.1.0",
+        "globals": "11.3.0",
+        "invariant": "2.2.3",
+        "lodash": "4.17.5"
+      }
+    },
+    "@babel/types": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.40.tgz",
+      "integrity": "sha512-uXCGCzTgMZxcSUzutCPtZmXbVC+cvENgS2e0tRuhn+Y1hZnMb8IHP0Trq7Q2MB/eFmG5pKrAeTIUfQIe5kA4Tg==",
+      "requires": {
+        "esutils": "2.0.2",
+        "lodash": "4.17.5",
+        "to-fast-properties": "2.0.0"
+      }
+    },
     "@f/animate": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/@f/animate/-/animate-1.0.1.tgz",
@@ -45,6 +130,12 @@
         "@f/map-obj": "1.2.2"
       }
     },
+    "@sindresorhus/is": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
+      "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==",
+      "dev": true
+    },
     "@types/babel-types": {
       "version": "7.0.1",
       "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.1.tgz",
@@ -68,9 +159,9 @@
       }
     },
     "@types/events": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@types/events/-/events-1.1.0.tgz",
-      "integrity": "sha512-y3bR98mzYOo0pAZuiLari+cQyiKk3UXRuT45h1RjhfeCzqkjaVsfZJNaxdgtk7/3tzOm1ozLTqEqMP3VbI48jw=="
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
+      "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA=="
     },
     "@types/express": {
       "version": "4.11.1",
@@ -87,7 +178,7 @@
       "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.11.1.tgz",
       "integrity": "sha512-EehCl3tpuqiM8RUb+0255M8PhhSwTtLfmO7zBBdv0ay/VTd/zmrqDfQdZFsa5z/PVMbH2yCMZPXsnrImpATyIw==",
       "requires": {
-        "@types/events": "1.1.0",
+        "@types/events": "1.2.0",
         "@types/node": "9.4.6"
       }
     },
@@ -96,7 +187,7 @@
       "resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-1.0.3.tgz",
       "integrity": "sha512-FSj24s1WsFEfOy8taIKp2DokSZfFkjWYZb88AS5eDj3WTocZ+4DnHjhzrXEs048WQ5mfOLJXMOAnc0kSnHh5Lw==",
       "requires": {
-        "@types/events": "1.1.0",
+        "@types/events": "1.2.0",
         "@types/node": "9.4.6"
       }
     },
@@ -134,31 +225,33 @@
       "dev": true
     },
     "accepts": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
-      "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=",
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
+      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
       "requires": {
         "mime-types": "2.1.18",
         "negotiator": "0.6.1"
       }
     },
     "acorn": {
-      "version": "5.4.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz",
-      "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ=="
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+      "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
     },
     "acorn-dynamic-import": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz",
-      "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz",
+      "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==",
+      "dev": true,
       "requires": {
-        "acorn": "4.0.13"
+        "acorn": "5.5.1"
       },
       "dependencies": {
         "acorn": {
-          "version": "4.0.13",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
-          "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
+          "version": "5.5.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.1.tgz",
+          "integrity": "sha512-D/KGiCpM/VOtTMDS+wfjywEth926WUrArrzYov4N4SI7t+3y8747dPpCmmAvrm/Z3ygqMHnyPxvYYO0yTdn/nQ==",
+          "dev": true
         }
       }
     },
@@ -184,32 +277,22 @@
       "dev": true,
       "requires": {
         "acorn": "3.3.0"
-      },
-      "dependencies": {
-        "acorn": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-          "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
-          "dev": true
-        }
       }
     },
     "ajv": {
-      "version": "5.5.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.1.tgz",
+      "integrity": "sha1-KKarxJOiq+D7TIUHrK7bQ/pVBnE=",
       "requires": {
-        "co": "4.6.0",
-        "fast-deep-equal": "1.0.0",
+        "fast-deep-equal": "1.1.0",
         "fast-json-stable-stringify": "2.0.0",
         "json-schema-traverse": "0.3.1"
       }
     },
     "ajv-keywords": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
-      "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
-      "dev": true
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz",
+      "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74="
     },
     "align-text": {
       "version": "0.1.4",
@@ -252,25 +335,32 @@
       "dev": true
     },
     "ansi-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-      "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+      "dev": true
     },
     "ansi-styles": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
-      "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
       "requires": {
         "color-convert": "1.9.1"
       }
     },
+    "any-observable": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz",
+      "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=",
+      "dev": true
+    },
     "anymatch": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
       "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
       "dev": true,
       "requires": {
-        "micromatch": "3.1.8",
+        "micromatch": "3.1.9",
         "normalize-path": "2.1.1"
       }
     },
@@ -288,7 +378,7 @@
       "integrity": "sha512-6Ghf+j3cQLCIvjXd2dJrLw+16HZbWbwmB1qlTc41BviB2hv+rK1nJr17Y9dWK0UD4p3i9Hfddx3tthpMKrueHg==",
       "requires": {
         "@types/node": "9.4.6",
-        "apollo-utilities": "1.0.8",
+        "apollo-utilities": "1.0.9",
         "zen-observable-ts": "0.8.8"
       }
     },
@@ -325,9 +415,14 @@
       }
     },
     "apollo-utilities": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.8.tgz",
-      "integrity": "sha512-EvqRJCw5xy2gWeH37toUimbEkmUxronCosBNE4tOCJvZUMLLGB8CuTQ5RsBhKJm+rZ6kwGxV+2uszk14f/P/rA=="
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.9.tgz",
+      "integrity": "sha512-6j04GLQr5EM76uzLrGWehXc/uKvvKaFMDD4ru7FzlfKjNAf+g399TRneF/LMyQzkwRaM4atYyPIhIJOruNDV/A=="
+    },
+    "aproba": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
     },
     "argparse": {
       "version": "1.0.10",
@@ -338,6 +433,12 @@
         "sprintf-js": "1.0.3"
       }
     },
+    "argv": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz",
+      "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=",
+      "dev": true
+    },
     "arr-diff": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
@@ -353,6 +454,12 @@
       "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
       "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
     },
+    "array-differ": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
+      "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
+      "dev": true
+    },
     "array-each": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
@@ -372,7 +479,6 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
       "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-      "dev": true,
       "requires": {
         "array-uniq": "1.0.3"
       }
@@ -380,8 +486,7 @@
     "array-uniq": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-      "dev": true
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
     },
     "array-unique": {
       "version": "0.3.2",
@@ -391,8 +496,7 @@
     "arrify": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
-      "dev": true
+      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
     },
     "asap": {
       "version": "2.0.6",
@@ -408,6 +512,7 @@
       "version": "4.10.1",
       "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
       "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+      "dev": true,
       "requires": {
         "bn.js": "4.11.8",
         "inherits": "2.0.3",
@@ -418,6 +523,7 @@
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
       "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+      "dev": true,
       "requires": {
         "util": "0.10.3"
       }
@@ -432,24 +538,47 @@
       "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
       "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
     },
+    "ast-types": {
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz",
+      "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==",
+      "dev": true
+    },
     "async": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
-      "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
-      "requires": {
-        "lodash": "4.17.5"
-      }
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+      "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+      "dev": true
     },
     "async-each": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
-      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0="
+      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+      "dev": true
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+      "dev": true
     },
     "atob": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz",
       "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10="
     },
+    "aws-sign2": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+      "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
+      "dev": true
+    },
+    "aws4": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
+      "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
+      "dev": true
+    },
     "babel-code-frame": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
@@ -461,12 +590,6 @@
         "js-tokens": "3.0.2"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-          "dev": true
-        },
         "ansi-styles": {
           "version": "2.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
@@ -503,152 +626,1036 @@
         }
       }
     },
-    "babel-runtime": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
-      "requires": {
-        "core-js": "2.5.3",
-        "regenerator-runtime": "0.11.1"
-      }
-    },
-    "babel-types": {
+    "babel-core": {
       "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
-      "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+      "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz",
+      "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=",
+      "dev": true,
       "requires": {
+        "babel-code-frame": "6.26.0",
+        "babel-generator": "6.26.1",
+        "babel-helpers": "6.24.1",
+        "babel-messages": "6.23.0",
+        "babel-register": "6.26.0",
         "babel-runtime": "6.26.0",
-        "esutils": "2.0.2",
+        "babel-template": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0",
+        "babylon": "6.18.0",
+        "convert-source-map": "1.5.1",
+        "debug": "2.6.9",
+        "json5": "0.5.1",
         "lodash": "4.17.5",
-        "to-fast-properties": "1.0.3"
+        "minimatch": "3.0.4",
+        "path-is-absolute": "1.0.1",
+        "private": "0.1.8",
+        "slash": "1.0.0",
+        "source-map": "0.5.7"
+      },
+      "dependencies": {
+        "babylon": {
+          "version": "6.18.0",
+          "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+          "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+          "dev": true
+        },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
       }
     },
-    "babylon": {
-      "version": "7.0.0-beta.19",
-      "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz",
-      "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==",
-      "dev": true
-    },
-    "backoff": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz",
-      "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=",
+    "babel-eslint": {
+      "version": "8.2.2",
+      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.2.tgz",
+      "integrity": "sha512-Qt2lz2egBxNYWqN9JIO2z4NOOf8i4b5JS6CFoYrOZZTDssueiV1jH/jsefyg+86SeNY3rB361/mi3kE1WK2WYQ==",
       "requires": {
-        "precond": "0.2.3"
+        "@babel/code-frame": "7.0.0-beta.40",
+        "@babel/traverse": "7.0.0-beta.40",
+        "@babel/types": "7.0.0-beta.40",
+        "babylon": "7.0.0-beta.40",
+        "eslint-scope": "3.7.1",
+        "eslint-visitor-keys": "1.0.0"
       }
     },
-    "balanced-match": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
-    },
-    "base": {
-      "version": "0.11.2",
-      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
-      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+    "babel-generator": {
+      "version": "6.26.1",
+      "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
+      "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
+      "dev": true,
       "requires": {
-        "cache-base": "1.0.1",
-        "class-utils": "0.3.6",
-        "component-emitter": "1.2.1",
-        "define-property": "1.0.0",
-        "isobject": "3.0.1",
-        "mixin-deep": "1.3.1",
-        "pascalcase": "0.1.1"
+        "babel-messages": "6.23.0",
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0",
+        "detect-indent": "4.0.0",
+        "jsesc": "1.3.0",
+        "lodash": "4.17.5",
+        "source-map": "0.5.7",
+        "trim-right": "1.0.1"
       },
       "dependencies": {
-        "define-property": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-          "requires": {
-            "is-descriptor": "1.0.2"
-          }
+        "jsesc": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+          "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
+          "dev": true
         }
       }
     },
-    "base64-js": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz",
-      "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w=="
-    },
-    "basic-auth": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz",
-      "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=",
+    "babel-helper-bindify-decorators": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz",
+      "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=",
+      "dev": true,
       "requires": {
-        "safe-buffer": "5.1.1"
+        "babel-runtime": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0"
       }
     },
-    "bcryptjs": {
-      "version": "2.4.3",
-      "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
-      "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
-    },
-    "big.js": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
-      "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
-    },
-    "binary-extensions": {
-      "version": "1.11.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
-      "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU="
+    "babel-helper-builder-binary-assignment-operator-visitor": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
+      "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
+      "dev": true,
+      "requires": {
+        "babel-helper-explode-assignable-expression": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0"
+      }
     },
-    "bluebird": {
-      "version": "3.5.1",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
-      "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
+    "babel-helper-call-delegate": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
+      "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
+      "dev": true,
+      "requires": {
+        "babel-helper-hoist-variables": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0"
+      }
     },
-    "bn.js": {
-      "version": "4.11.8",
-      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
-      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
+    "babel-helper-define-map": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
+      "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
+      "dev": true,
+      "requires": {
+        "babel-helper-function-name": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0",
+        "lodash": "4.17.5"
+      }
     },
-    "body-parser": {
-      "version": "1.18.2",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
-      "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
+    "babel-helper-explode-assignable-expression": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
+      "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
+      "dev": true,
       "requires": {
-        "bytes": "3.0.0",
-        "content-type": "1.0.4",
-        "debug": "2.6.9",
-        "depd": "1.1.2",
-        "http-errors": "1.6.2",
-        "iconv-lite": "0.4.19",
-        "on-finished": "2.3.0",
-        "qs": "6.5.1",
-        "raw-body": "2.3.2",
-        "type-is": "1.6.16"
+        "babel-runtime": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0"
       }
     },
-    "boxen": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
-      "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
+    "babel-helper-explode-class": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz",
+      "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=",
       "dev": true,
       "requires": {
-        "ansi-align": "2.0.0",
-        "camelcase": "4.1.0",
-        "chalk": "2.3.1",
-        "cli-boxes": "1.0.0",
-        "string-width": "2.1.1",
-        "term-size": "1.2.0",
-        "widest-line": "2.0.0"
+        "babel-helper-bindify-decorators": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0"
       }
     },
-    "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+    "babel-helper-function-name": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
+      "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
+      "dev": true,
       "requires": {
-        "balanced-match": "1.0.0",
-        "concat-map": "0.0.1"
+        "babel-helper-get-function-arity": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0"
       }
     },
-    "braces": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz",
-      "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==",
+    "babel-helper-get-function-arity": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
+      "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-helper-hoist-variables": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
+      "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-helper-optimise-call-expression": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
+      "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-helper-regex": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
+      "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0",
+        "lodash": "4.17.5"
+      }
+    },
+    "babel-helper-remap-async-to-generator": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
+      "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
+      "dev": true,
+      "requires": {
+        "babel-helper-function-name": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-helper-replace-supers": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
+      "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
+      "dev": true,
+      "requires": {
+        "babel-helper-optimise-call-expression": "6.24.1",
+        "babel-messages": "6.23.0",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-helpers": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
+      "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0"
+      }
+    },
+    "babel-messages": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+      "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-check-es2015-constants": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
+      "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-syntax-async-functions": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+      "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
+      "dev": true
+    },
+    "babel-plugin-syntax-async-generators": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
+      "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=",
+      "dev": true
+    },
+    "babel-plugin-syntax-class-constructor-call": {
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz",
+      "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=",
+      "dev": true
+    },
+    "babel-plugin-syntax-class-properties": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
+      "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=",
+      "dev": true
+    },
+    "babel-plugin-syntax-decorators": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
+      "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
+      "dev": true
+    },
+    "babel-plugin-syntax-dynamic-import": {
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
+      "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=",
+      "dev": true
+    },
+    "babel-plugin-syntax-exponentiation-operator": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
+      "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
+      "dev": true
+    },
+    "babel-plugin-syntax-export-extensions": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz",
+      "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=",
+      "dev": true
+    },
+    "babel-plugin-syntax-flow": {
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
+      "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=",
+      "dev": true
+    },
+    "babel-plugin-syntax-object-rest-spread": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
+      "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
+      "dev": true
+    },
+    "babel-plugin-syntax-trailing-function-commas": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
+      "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=",
+      "dev": true
+    },
+    "babel-plugin-transform-async-generator-functions": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz",
+      "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=",
+      "dev": true,
+      "requires": {
+        "babel-helper-remap-async-to-generator": "6.24.1",
+        "babel-plugin-syntax-async-generators": "6.13.0",
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-async-to-generator": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
+      "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
+      "dev": true,
+      "requires": {
+        "babel-helper-remap-async-to-generator": "6.24.1",
+        "babel-plugin-syntax-async-functions": "6.13.0",
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-class-constructor-call": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz",
+      "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-syntax-class-constructor-call": "6.18.0",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-class-properties": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz",
+      "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=",
+      "dev": true,
+      "requires": {
+        "babel-helper-function-name": "6.24.1",
+        "babel-plugin-syntax-class-properties": "6.13.0",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-decorators": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz",
+      "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=",
+      "dev": true,
+      "requires": {
+        "babel-helper-explode-class": "6.24.1",
+        "babel-plugin-syntax-decorators": "6.13.0",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-arrow-functions": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
+      "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-block-scoped-functions": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
+      "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-block-scoping": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
+      "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0",
+        "lodash": "4.17.5"
+      }
+    },
+    "babel-plugin-transform-es2015-classes": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
+      "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
+      "dev": true,
+      "requires": {
+        "babel-helper-define-map": "6.26.0",
+        "babel-helper-function-name": "6.24.1",
+        "babel-helper-optimise-call-expression": "6.24.1",
+        "babel-helper-replace-supers": "6.24.1",
+        "babel-messages": "6.23.0",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-computed-properties": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
+      "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-destructuring": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
+      "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-duplicate-keys": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
+      "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-for-of": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
+      "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-function-name": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
+      "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
+      "dev": true,
+      "requires": {
+        "babel-helper-function-name": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-literals": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
+      "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-amd": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
+      "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-transform-es2015-modules-commonjs": "6.26.0",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-commonjs": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz",
+      "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-transform-strict-mode": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-systemjs": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
+      "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
+      "dev": true,
+      "requires": {
+        "babel-helper-hoist-variables": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-umd": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
+      "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-transform-es2015-modules-amd": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-object-super": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
+      "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
+      "dev": true,
+      "requires": {
+        "babel-helper-replace-supers": "6.24.1",
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-parameters": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
+      "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
+      "dev": true,
+      "requires": {
+        "babel-helper-call-delegate": "6.24.1",
+        "babel-helper-get-function-arity": "6.24.1",
+        "babel-runtime": "6.26.0",
+        "babel-template": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-shorthand-properties": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
+      "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-spread": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
+      "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-sticky-regex": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
+      "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
+      "dev": true,
+      "requires": {
+        "babel-helper-regex": "6.26.0",
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-template-literals": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
+      "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-typeof-symbol": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
+      "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-unicode-regex": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
+      "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
+      "dev": true,
+      "requires": {
+        "babel-helper-regex": "6.26.0",
+        "babel-runtime": "6.26.0",
+        "regexpu-core": "2.0.0"
+      }
+    },
+    "babel-plugin-transform-exponentiation-operator": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
+      "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
+      "dev": true,
+      "requires": {
+        "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1",
+        "babel-plugin-syntax-exponentiation-operator": "6.13.0",
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-export-extensions": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz",
+      "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-syntax-export-extensions": "6.13.0",
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-flow-strip-types": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz",
+      "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-syntax-flow": "6.18.0",
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-object-rest-spread": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz",
+      "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-syntax-object-rest-spread": "6.13.0",
+        "babel-runtime": "6.26.0"
+      }
+    },
+    "babel-plugin-transform-regenerator": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
+      "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
+      "dev": true,
+      "requires": {
+        "regenerator-transform": "0.10.1"
+      }
+    },
+    "babel-plugin-transform-strict-mode": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
+      "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0"
+      }
+    },
+    "babel-preset-es2015": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz",
+      "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-check-es2015-constants": "6.22.0",
+        "babel-plugin-transform-es2015-arrow-functions": "6.22.0",
+        "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0",
+        "babel-plugin-transform-es2015-block-scoping": "6.26.0",
+        "babel-plugin-transform-es2015-classes": "6.24.1",
+        "babel-plugin-transform-es2015-computed-properties": "6.24.1",
+        "babel-plugin-transform-es2015-destructuring": "6.23.0",
+        "babel-plugin-transform-es2015-duplicate-keys": "6.24.1",
+        "babel-plugin-transform-es2015-for-of": "6.23.0",
+        "babel-plugin-transform-es2015-function-name": "6.24.1",
+        "babel-plugin-transform-es2015-literals": "6.22.0",
+        "babel-plugin-transform-es2015-modules-amd": "6.24.1",
+        "babel-plugin-transform-es2015-modules-commonjs": "6.26.0",
+        "babel-plugin-transform-es2015-modules-systemjs": "6.24.1",
+        "babel-plugin-transform-es2015-modules-umd": "6.24.1",
+        "babel-plugin-transform-es2015-object-super": "6.24.1",
+        "babel-plugin-transform-es2015-parameters": "6.24.1",
+        "babel-plugin-transform-es2015-shorthand-properties": "6.24.1",
+        "babel-plugin-transform-es2015-spread": "6.22.0",
+        "babel-plugin-transform-es2015-sticky-regex": "6.24.1",
+        "babel-plugin-transform-es2015-template-literals": "6.22.0",
+        "babel-plugin-transform-es2015-typeof-symbol": "6.23.0",
+        "babel-plugin-transform-es2015-unicode-regex": "6.24.1",
+        "babel-plugin-transform-regenerator": "6.26.0"
+      }
+    },
+    "babel-preset-stage-1": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz",
+      "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-transform-class-constructor-call": "6.24.1",
+        "babel-plugin-transform-export-extensions": "6.22.0",
+        "babel-preset-stage-2": "6.24.1"
+      }
+    },
+    "babel-preset-stage-2": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz",
+      "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-syntax-dynamic-import": "6.18.0",
+        "babel-plugin-transform-class-properties": "6.24.1",
+        "babel-plugin-transform-decorators": "6.24.1",
+        "babel-preset-stage-3": "6.24.1"
+      }
+    },
+    "babel-preset-stage-3": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz",
+      "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=",
+      "dev": true,
+      "requires": {
+        "babel-plugin-syntax-trailing-function-commas": "6.22.0",
+        "babel-plugin-transform-async-generator-functions": "6.24.1",
+        "babel-plugin-transform-async-to-generator": "6.24.1",
+        "babel-plugin-transform-exponentiation-operator": "6.24.1",
+        "babel-plugin-transform-object-rest-spread": "6.26.0"
+      }
+    },
+    "babel-register": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
+      "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
+      "dev": true,
+      "requires": {
+        "babel-core": "6.26.0",
+        "babel-runtime": "6.26.0",
+        "core-js": "2.5.3",
+        "home-or-tmp": "2.0.0",
+        "lodash": "4.17.5",
+        "mkdirp": "0.5.1",
+        "source-map-support": "0.4.18"
+      },
+      "dependencies": {
+        "source-map-support": {
+          "version": "0.4.18",
+          "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
+          "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
+          "dev": true,
+          "requires": {
+            "source-map": "0.5.7"
+          }
+        }
+      }
+    },
+    "babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+      "requires": {
+        "core-js": "2.5.3",
+        "regenerator-runtime": "0.11.1"
+      }
+    },
+    "babel-template": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+      "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-traverse": "6.26.0",
+        "babel-types": "6.26.0",
+        "babylon": "6.18.0",
+        "lodash": "4.17.5"
+      },
+      "dependencies": {
+        "babylon": {
+          "version": "6.18.0",
+          "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+          "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+          "dev": true
+        }
+      }
+    },
+    "babel-traverse": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+      "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+      "dev": true,
+      "requires": {
+        "babel-code-frame": "6.26.0",
+        "babel-messages": "6.23.0",
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0",
+        "babylon": "6.18.0",
+        "debug": "2.6.9",
+        "globals": "9.18.0",
+        "invariant": "2.2.3",
+        "lodash": "4.17.5"
+      },
+      "dependencies": {
+        "babylon": {
+          "version": "6.18.0",
+          "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+          "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+          "dev": true
+        },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "globals": {
+          "version": "9.18.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+          "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+          "dev": true
+        }
+      }
+    },
+    "babel-types": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+      "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "esutils": "2.0.2",
+        "lodash": "4.17.5",
+        "to-fast-properties": "1.0.3"
+      },
+      "dependencies": {
+        "to-fast-properties": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+          "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
+        }
+      }
+    },
+    "babylon": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.40.tgz",
+      "integrity": "sha512-AVxF2EcxvGD5hhOuLTOLAXBb0VhwWpEX0HyHdAI2zU+AAP4qEwtQj8voz1JR3uclGai0rfcE+dCTHnNMOnimFg=="
+    },
+    "backoff": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz",
+      "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=",
+      "requires": {
+        "precond": "0.2.3"
+      }
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+    },
+    "base": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+      "requires": {
+        "cache-base": "1.0.1",
+        "class-utils": "0.3.6",
+        "component-emitter": "1.2.1",
+        "define-property": "1.0.0",
+        "isobject": "3.0.1",
+        "mixin-deep": "1.3.1",
+        "pascalcase": "0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "requires": {
+            "is-descriptor": "1.0.2"
+          }
+        }
+      }
+    },
+    "base64-js": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz",
+      "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==",
+      "dev": true
+    },
+    "basic-auth": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz",
+      "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=",
+      "requires": {
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "bcrypt-pbkdf": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
+      "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "tweetnacl": "0.14.5"
+      }
+    },
+    "bcryptjs": {
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+      "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
+    },
+    "big.js": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
+      "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
+    },
+    "binary-extensions": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
+      "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
+      "dev": true
+    },
+    "binaryextensions": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz",
+      "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==",
+      "dev": true
+    },
+    "bluebird": {
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
+      "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
+    },
+    "bn.js": {
+      "version": "4.11.8",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+      "dev": true
+    },
+    "body-parser": {
+      "version": "1.18.2",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
+      "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
+      "requires": {
+        "bytes": "3.0.0",
+        "content-type": "1.0.4",
+        "debug": "2.6.9",
+        "depd": "1.1.2",
+        "http-errors": "1.6.2",
+        "iconv-lite": "0.4.19",
+        "on-finished": "2.3.0",
+        "qs": "6.5.1",
+        "raw-body": "2.3.2",
+        "type-is": "1.6.16"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "boom": {
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+      "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
+      "dev": true,
+      "requires": {
+        "hoek": "2.16.3"
+      }
+    },
+    "boxen": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
+      "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
+      "dev": true,
+      "requires": {
+        "ansi-align": "2.0.0",
+        "camelcase": "4.1.0",
+        "chalk": "2.3.2",
+        "cli-boxes": "1.0.0",
+        "string-width": "2.1.1",
+        "term-size": "1.2.0",
+        "widest-line": "2.0.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+          "dev": true
+        }
+      }
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "requires": {
+        "balanced-match": "1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz",
+      "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==",
       "requires": {
         "arr-flatten": "1.1.0",
         "array-unique": "0.3.2",
@@ -661,7 +1668,7 @@
         "snapdragon": "0.8.1",
         "snapdragon-node": "2.1.1",
         "split-string": "3.1.0",
-        "to-regex": "3.0.1"
+        "to-regex": "3.0.2"
       },
       "dependencies": {
         "define-property": {
@@ -685,12 +1692,14 @@
     "brorand": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
-      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+      "dev": true
     },
     "browserify-aes": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz",
       "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==",
+      "dev": true,
       "requires": {
         "buffer-xor": "1.0.3",
         "cipher-base": "1.0.4",
@@ -704,6 +1713,7 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz",
       "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=",
+      "dev": true,
       "requires": {
         "browserify-aes": "1.1.1",
         "browserify-des": "1.0.0",
@@ -714,6 +1724,7 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz",
       "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=",
+      "dev": true,
       "requires": {
         "cipher-base": "1.0.4",
         "des.js": "1.0.0",
@@ -724,6 +1735,7 @@
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
       "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+      "dev": true,
       "requires": {
         "bn.js": "4.11.8",
         "randombytes": "2.0.6"
@@ -733,6 +1745,7 @@
       "version": "4.0.4",
       "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
       "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+      "dev": true,
       "requires": {
         "bn.js": "4.11.8",
         "browserify-rsa": "4.0.1",
@@ -747,6 +1760,7 @@
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
       "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+      "dev": true,
       "requires": {
         "pako": "1.0.6"
       }
@@ -755,6 +1769,7 @@
       "version": "4.9.1",
       "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
       "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+      "dev": true,
       "requires": {
         "base64-js": "1.2.3",
         "ieee754": "1.1.8",
@@ -769,17 +1784,20 @@
     "buffer-xor": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
-      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+      "dev": true
     },
     "builtin-modules": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+      "dev": true
     },
     "builtin-status-codes": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
-      "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
+      "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+      "dev": true
     },
     "bunyan": {
       "version": "1.8.12",
@@ -787,7 +1805,7 @@
       "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
       "requires": {
         "dtrace-provider": "0.8.6",
-        "moment": "2.20.1",
+        "moment": "2.21.0",
         "mv": "2.1.1",
         "safe-json-stringify": "1.1.0"
       }
@@ -797,6 +1815,26 @@
       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
       "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
     },
+    "cacache": {
+      "version": "10.0.4",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+      "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
+      "requires": {
+        "bluebird": "3.5.1",
+        "chownr": "1.0.1",
+        "glob": "7.1.2",
+        "graceful-fs": "4.1.11",
+        "lru-cache": "4.1.1",
+        "mississippi": "2.0.0",
+        "mkdirp": "0.5.1",
+        "move-concurrently": "1.0.1",
+        "promise-inflight": "1.0.1",
+        "rimraf": "2.6.2",
+        "ssri": "5.2.4",
+        "unique-filename": "1.1.0",
+        "y18n": "4.0.0"
+      }
+    },
     "cache-base": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
@@ -813,6 +1851,21 @@
         "unset-value": "1.0.0"
       }
     },
+    "cacheable-request": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz",
+      "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=",
+      "dev": true,
+      "requires": {
+        "clone-response": "1.0.2",
+        "get-stream": "3.0.0",
+        "http-cache-semantics": "3.8.1",
+        "keyv": "3.0.0",
+        "lowercase-keys": "1.0.0",
+        "normalize-url": "2.0.1",
+        "responselike": "1.0.2"
+      }
+    },
     "caller-path": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
@@ -829,9 +1882,9 @@
       "dev": true
     },
     "camelcase": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-      "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+      "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
     },
     "capture-stack-trace": {
       "version": "1.0.0",
@@ -839,6 +1892,12 @@
       "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=",
       "dev": true
     },
+    "caseless": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+      "dev": true
+    },
     "catharsis": {
       "version": "0.8.9",
       "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz",
@@ -870,14 +1929,13 @@
       "integrity": "sha1-DUqzfn4Y6tC9xHuSB2QRjOWHM9w="
     },
     "chalk": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz",
-      "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==",
-      "dev": true,
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz",
+      "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==",
       "requires": {
-        "ansi-styles": "3.2.0",
+        "ansi-styles": "3.2.1",
         "escape-string-regexp": "1.0.5",
-        "supports-color": "5.2.0"
+        "supports-color": "5.3.0"
       }
     },
     "character-parser": {
@@ -914,10 +1972,22 @@
         "upath": "1.0.4"
       }
     },
+    "chownr": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
+      "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE="
+    },
+    "chrome-trace-event": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-0.1.2.tgz",
+      "integrity": "sha1-kPNohdU0WlBiEzLwcXtZWIPV2YI=",
+      "dev": true
+    },
     "cipher-base": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
       "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "dev": true,
       "requires": {
         "inherits": "2.0.3",
         "safe-buffer": "5.1.1"
@@ -1048,6 +2118,76 @@
         "restore-cursor": "2.0.0"
       }
     },
+    "cli-spinners": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz",
+      "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=",
+      "dev": true
+    },
+    "cli-table": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz",
+      "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=",
+      "dev": true,
+      "requires": {
+        "colors": "1.0.3"
+      },
+      "dependencies": {
+        "colors": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+          "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
+          "dev": true
+        }
+      }
+    },
+    "cli-truncate": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
+      "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=",
+      "dev": true,
+      "requires": {
+        "slice-ansi": "0.0.4",
+        "string-width": "1.0.2"
+      },
+      "dependencies": {
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
+          "requires": {
+            "number-is-nan": "1.0.1"
+          }
+        },
+        "slice-ansi": {
+          "version": "0.0.4",
+          "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
+          "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
+          "dev": true
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+          "dev": true,
+          "requires": {
+            "code-point-at": "1.1.0",
+            "is-fullwidth-code-point": "1.0.0",
+            "strip-ansi": "3.0.1"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "2.1.1"
+          }
+        }
+      }
+    },
     "cli-width": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
@@ -1072,12 +2212,51 @@
         "center-align": "0.1.3",
         "right-align": "0.1.3",
         "wordwrap": "0.0.2"
+      }
+    },
+    "clone": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz",
+      "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=",
+      "dev": true
+    },
+    "clone-buffer": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz",
+      "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=",
+      "dev": true
+    },
+    "clone-response": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
+      "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+      "dev": true,
+      "requires": {
+        "mimic-response": "1.0.0"
+      }
+    },
+    "clone-stats": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
+      "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
+      "dev": true
+    },
+    "cloneable-readable": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz",
+      "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3",
+        "process-nextick-args": "1.0.7",
+        "through2": "2.0.3"
       },
       "dependencies": {
-        "wordwrap": {
-          "version": "0.0.2",
-          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
-          "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
+        "process-nextick-args": {
+          "version": "1.0.7",
+          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+          "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+          "dev": true
         }
       }
     },
@@ -1089,7 +2268,19 @@
     "code-point-at": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
-      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "dev": true
+    },
+    "codecov": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.0.0.tgz",
+      "integrity": "sha1-wnO4xPEpRXI+jcnSWAPYk0Pl8o4=",
+      "dev": true,
+      "requires": {
+        "argv": "0.0.2",
+        "request": "2.81.0",
+        "urlgrey": "0.4.4"
+      }
     },
     "collection-visit": {
       "version": "1.0.0",
@@ -1118,11 +2309,25 @@
       "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
       "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM="
     },
+    "combined-stream": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
+      "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
+      "dev": true,
+      "requires": {
+        "delayed-stream": "1.0.0"
+      }
+    },
     "commander": {
       "version": "2.14.1",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz",
       "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw=="
     },
+    "commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
+    },
     "commonmark": {
       "version": "0.28.1",
       "resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.28.1.tgz",
@@ -1132,6 +2337,13 @@
         "mdurl": "1.0.1",
         "minimist": "1.2.0",
         "string.prototype.repeat": "0.2.0"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+        }
       }
     },
     "component-emitter": {
@@ -1145,13 +2357,12 @@
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
     "concat-stream": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
-      "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
-      "dev": true,
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.1.tgz",
+      "integrity": "sha512-gslSSJx03QKa59cIKqeJO9HQ/WZMotvYJCuaUULrLpjj8oG40kV2Z+gz82pVxlTkOADi4PJxQPPfhl1ELYrrXw==",
       "requires": {
         "inherits": "2.0.3",
-        "readable-stream": "2.3.4",
+        "readable-stream": "2.3.5",
         "typedarray": "0.0.6"
       }
     },
@@ -1183,6 +2394,7 @@
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
       "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+      "dev": true,
       "requires": {
         "date-now": "0.1.4"
       }
@@ -1208,7 +2420,8 @@
     "constants-browserify": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
-      "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+      "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+      "dev": true
     },
     "contains-path": {
       "version": "0.1.0",
@@ -1226,6 +2439,12 @@
       "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
       "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
     },
+    "convert-source-map": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
+      "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=",
+      "dev": true
+    },
     "cookie": {
       "version": "0.3.1",
       "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
@@ -1236,11 +2455,39 @@
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
     },
+    "copy-concurrently": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+      "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+      "requires": {
+        "aproba": "1.2.0",
+        "fs-write-stream-atomic": "1.0.10",
+        "iferr": "0.1.5",
+        "mkdirp": "0.5.1",
+        "rimraf": "2.6.2",
+        "run-queue": "1.0.3"
+      }
+    },
     "copy-descriptor": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
       "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
     },
+    "copy-webpack-plugin": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.0.tgz",
+      "integrity": "sha512-ROQ85fWKuhJfUkBTdHvfV+Zv6Ltm3G/vPVFdLPFwzWzd9RUY1yLw3rt6FmKK2PaeNQCNvmwgFhuarkjuV4PVDQ==",
+      "requires": {
+        "cacache": "10.0.4",
+        "find-cache-dir": "1.0.0",
+        "globby": "7.1.1",
+        "is-glob": "4.0.0",
+        "loader-utils": "1.1.0",
+        "minimatch": "3.0.4",
+        "p-limit": "1.2.0",
+        "serialize-javascript": "1.4.0"
+      }
+    },
     "core-js": {
       "version": "2.5.3",
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz",
@@ -1269,6 +2516,7 @@
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
       "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=",
+      "dev": true,
       "requires": {
         "bn.js": "4.11.8",
         "elliptic": "6.4.0"
@@ -1287,6 +2535,7 @@
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
       "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=",
+      "dev": true,
       "requires": {
         "cipher-base": "1.0.4",
         "inherits": "2.0.3",
@@ -1298,6 +2547,7 @@
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz",
       "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=",
+      "dev": true,
       "requires": {
         "cipher-base": "1.0.4",
         "create-hash": "1.1.3",
@@ -1320,16 +2570,27 @@
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
       "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+      "dev": true,
+      "requires": {
+        "lru-cache": "4.1.1",
+        "shebang-command": "1.2.0",
+        "which": "1.3.0"
+      }
+    },
+    "cryptiles": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+      "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
+      "dev": true,
       "requires": {
-        "lru-cache": "4.1.1",
-        "shebang-command": "1.2.0",
-        "which": "1.3.0"
+        "boom": "2.10.1"
       }
     },
     "crypto-browserify": {
       "version": "3.12.0",
       "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
       "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+      "dev": true,
       "requires": {
         "browserify-cipher": "1.0.0",
         "browserify-sign": "4.0.4",
@@ -1350,13 +2611,16 @@
       "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
       "dev": true
     },
-    "d": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
-      "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
-      "requires": {
-        "es5-ext": "0.10.39"
-      }
+    "cyclist": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
+      "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA="
+    },
+    "dargs": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz",
+      "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=",
+      "dev": true
     },
     "dashdash": {
       "version": "1.14.1",
@@ -1366,15 +2630,28 @@
         "assert-plus": "1.0.0"
       }
     },
+    "date-fns": {
+      "version": "1.29.0",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz",
+      "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==",
+      "dev": true
+    },
     "date-now": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
-      "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="
+      "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+      "dev": true
+    },
+    "dateformat": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
+      "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=",
+      "dev": true
     },
     "debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+      "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
       "requires": {
         "ms": "2.0.0"
       }
@@ -1389,6 +2666,15 @@
       "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
       "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
     },
+    "decompress-response": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+      "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+      "dev": true,
+      "requires": {
+        "mimic-response": "1.0.0"
+      }
+    },
     "deep-extend": {
       "version": "0.4.2",
       "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
@@ -1425,6 +2711,20 @@
         "rimraf": "2.6.2"
       },
       "dependencies": {
+        "globby": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+          "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+          "dev": true,
+          "requires": {
+            "array-union": "1.0.2",
+            "arrify": "1.0.1",
+            "glob": "7.1.2",
+            "object-assign": "4.1.1",
+            "pify": "2.3.0",
+            "pinkie-promise": "2.0.1"
+          }
+        },
         "pify": {
           "version": "2.3.0",
           "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
@@ -1433,6 +2733,12 @@
         }
       }
     },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+      "dev": true
+    },
     "delegate": {
       "version": "3.2.0",
       "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
@@ -1452,6 +2758,7 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
       "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+      "dev": true,
       "requires": {
         "inherits": "2.0.3",
         "minimalistic-assert": "1.0.0"
@@ -1462,21 +2769,52 @@
       "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
       "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
     },
+    "detect-conflict": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz",
+      "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=",
+      "dev": true
+    },
     "detect-file": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
       "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc="
     },
+    "detect-indent": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+      "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+      "dev": true,
+      "requires": {
+        "repeating": "2.0.1"
+      }
+    },
+    "diff": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+      "dev": true
+    },
     "diffie-hellman": {
       "version": "5.0.2",
       "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz",
       "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
+      "dev": true,
       "requires": {
         "bn.js": "4.11.8",
         "miller-rabin": "4.0.1",
         "randombytes": "2.0.6"
       }
     },
+    "dir-glob": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz",
+      "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==",
+      "requires": {
+        "arrify": "1.0.1",
+        "path-type": "3.0.0"
+      }
+    },
     "doctrine": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@@ -1496,10 +2834,17 @@
       "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz",
       "integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg=="
     },
+    "dom-walk": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
+      "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=",
+      "dev": true
+    },
     "domain-browser": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
-      "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="
+      "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+      "dev": true
     },
     "dot-prop": {
       "version": "4.2.0",
@@ -1531,15 +2876,55 @@
       "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
       "dev": true
     },
+    "duplexify": {
+      "version": "3.5.4",
+      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz",
+      "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==",
+      "requires": {
+        "end-of-stream": "1.4.1",
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.5",
+        "stream-shift": "1.0.0"
+      }
+    },
+    "ecc-jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+      "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "jsbn": "0.1.1"
+      }
+    },
+    "editions": {
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz",
+      "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==",
+      "dev": true
+    },
     "ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
     },
+    "ejs": {
+      "version": "2.5.7",
+      "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz",
+      "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=",
+      "dev": true
+    },
+    "elegant-spinner": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz",
+      "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=",
+      "dev": true
+    },
     "elliptic": {
       "version": "6.4.0",
       "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
       "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+      "dev": true,
       "requires": {
         "bn.js": "4.11.8",
         "brorand": "1.1.0",
@@ -1568,15 +2953,23 @@
         "iconv-lite": "0.4.19"
       }
     },
+    "end-of-stream": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+      "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+      "requires": {
+        "once": "1.4.0"
+      }
+    },
     "enhanced-resolve": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz",
-      "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz",
+      "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==",
+      "dev": true,
       "requires": {
         "graceful-fs": "4.1.11",
         "memory-fs": "0.4.1",
-        "object-assign": "4.1.1",
-        "tapable": "0.2.8"
+        "tapable": "1.0.0"
       }
     },
     "entities": {
@@ -1588,82 +2981,30 @@
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
       "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "dev": true,
       "requires": {
         "prr": "1.0.1"
       }
     },
+    "error": {
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz",
+      "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=",
+      "dev": true,
+      "requires": {
+        "string-template": "0.2.1",
+        "xtend": "4.0.1"
+      }
+    },
     "error-ex": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
       "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
+      "dev": true,
       "requires": {
         "is-arrayish": "0.2.1"
       }
     },
-    "es5-ext": {
-      "version": "0.10.39",
-      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.39.tgz",
-      "integrity": "sha512-AlaXZhPHl0po/uxMx1tyrlt1O86M6D5iVaDH8UgLfgek4kXTX6vzsRfJQWC2Ku+aG8pkw1XWzh9eTkwfVrsD5g==",
-      "requires": {
-        "es6-iterator": "2.0.3",
-        "es6-symbol": "3.1.1"
-      }
-    },
-    "es6-iterator": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
-      "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
-      "requires": {
-        "d": "1.0.0",
-        "es5-ext": "0.10.39",
-        "es6-symbol": "3.1.1"
-      }
-    },
-    "es6-map": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
-      "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
-      "requires": {
-        "d": "1.0.0",
-        "es5-ext": "0.10.39",
-        "es6-iterator": "2.0.3",
-        "es6-set": "0.1.5",
-        "es6-symbol": "3.1.1",
-        "event-emitter": "0.3.5"
-      }
-    },
-    "es6-set": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
-      "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
-      "requires": {
-        "d": "1.0.0",
-        "es5-ext": "0.10.39",
-        "es6-iterator": "2.0.3",
-        "es6-symbol": "3.1.1",
-        "event-emitter": "0.3.5"
-      }
-    },
-    "es6-symbol": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
-      "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
-      "requires": {
-        "d": "1.0.0",
-        "es5-ext": "0.10.39"
-      }
-    },
-    "es6-weak-map": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz",
-      "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
-      "requires": {
-        "d": "1.0.0",
-        "es5-ext": "0.10.39",
-        "es6-iterator": "2.0.3",
-        "es6-symbol": "3.1.1"
-      }
-    },
     "escape-html": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -1674,33 +3015,22 @@
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
     },
-    "escope": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
-      "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=",
-      "requires": {
-        "es6-map": "0.1.5",
-        "es6-weak-map": "2.0.2",
-        "esrecurse": "4.2.0",
-        "estraverse": "4.2.0"
-      }
-    },
     "eslint": {
-      "version": "4.18.1",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.1.tgz",
-      "integrity": "sha512-gPSfpSRCHre1GLxGmO68tZNxOlL2y7xBd95VcLD+Eo4S2js31YoMum3CAQIOaxY24hqYOMksMvW38xuuWKQTgw==",
+      "version": "4.18.2",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz",
+      "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==",
       "dev": true,
       "requires": {
         "ajv": "5.5.2",
         "babel-code-frame": "6.26.0",
-        "chalk": "2.3.1",
-        "concat-stream": "1.6.0",
+        "chalk": "2.3.2",
+        "concat-stream": "1.6.1",
         "cross-spawn": "5.1.0",
         "debug": "3.1.0",
         "doctrine": "2.1.0",
         "eslint-scope": "3.7.1",
         "eslint-visitor-keys": "1.0.0",
-        "espree": "3.5.3",
+        "espree": "3.5.4",
         "esquery": "1.0.0",
         "esutils": "2.0.2",
         "file-entry-cache": "2.0.0",
@@ -1711,7 +3041,7 @@
         "imurmurhash": "0.1.4",
         "inquirer": "3.3.0",
         "is-resolvable": "1.1.0",
-        "js-yaml": "3.10.0",
+        "js-yaml": "3.11.0",
         "json-stable-stringify-without-jsonify": "1.0.1",
         "levn": "0.3.0",
         "lodash": "4.17.5",
@@ -1730,14 +3060,23 @@
         "text-table": "0.2.0"
       },
       "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+        "ajv": {
+          "version": "5.5.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
           "dev": true,
           "requires": {
-            "ms": "2.0.0"
+            "co": "4.6.0",
+            "fast-deep-equal": "1.1.0",
+            "fast-json-stable-stringify": "2.0.0",
+            "json-schema-traverse": "0.3.1"
           }
+        },
+        "semver": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+          "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+          "dev": true
         }
       }
     },
@@ -1755,6 +3094,30 @@
       "requires": {
         "debug": "2.6.9",
         "resolve": "1.5.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "eslint-loader": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.0.0.tgz",
+      "integrity": "sha512-VxxGDI4bXzLk0+/jMt/0EkGMRKS9ox6Czx+yapMb9WJmcS/ZHhlhqcVUNgUjFBNp02j/2pZLdGOrG7EXyjoz/g==",
+      "dev": true,
+      "requires": {
+        "loader-fs-cache": "1.0.1",
+        "loader-utils": "1.1.0",
+        "object-assign": "4.1.1",
+        "object-hash": "1.2.0",
+        "rimraf": "2.6.2"
       }
     },
     "eslint-module-utils": {
@@ -1765,6 +3128,45 @@
       "requires": {
         "debug": "2.6.9",
         "pkg-dir": "1.0.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "find-up": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+          "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+          "dev": true,
+          "requires": {
+            "path-exists": "2.1.0",
+            "pinkie-promise": "2.0.1"
+          }
+        },
+        "path-exists": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+          "dev": true,
+          "requires": {
+            "pinkie-promise": "2.0.1"
+          }
+        },
+        "pkg-dir": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz",
+          "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
+          "dev": true,
+          "requires": {
+            "find-up": "1.1.2"
+          }
+        }
       }
     },
     "eslint-plugin-import": {
@@ -1785,6 +3187,15 @@
         "read-pkg-up": "2.0.0"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "doctrine": {
           "version": "1.5.0",
           "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
@@ -1807,6 +3218,14 @@
         "minimatch": "3.0.4",
         "resolve": "1.5.0",
         "semver": "5.5.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+          "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+          "dev": true
+        }
       }
     },
     "eslint-plugin-promise": {
@@ -1825,26 +3244,32 @@
       "version": "3.7.1",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
       "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
-      "dev": true,
       "requires": {
-        "esrecurse": "4.2.0",
+        "esrecurse": "4.2.1",
         "estraverse": "4.2.0"
       }
     },
     "eslint-visitor-keys": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
-      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
-      "dev": true
+      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ=="
     },
     "espree": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz",
-      "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==",
+      "version": "3.5.4",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
+      "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
       "dev": true,
       "requires": {
-        "acorn": "5.4.1",
+        "acorn": "5.5.1",
         "acorn-jsx": "3.0.1"
+      },
+      "dependencies": {
+        "acorn": {
+          "version": "5.5.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.1.tgz",
+          "integrity": "sha512-D/KGiCpM/VOtTMDS+wfjywEth926WUrArrzYov4N4SI7t+3y8747dPpCmmAvrm/Z3ygqMHnyPxvYYO0yTdn/nQ==",
+          "dev": true
+        }
       }
     },
     "esprima": {
@@ -1863,12 +3288,11 @@
       }
     },
     "esrecurse": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
-      "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=",
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
       "requires": {
-        "estraverse": "4.2.0",
-        "object-assign": "4.1.1"
+        "estraverse": "4.2.0"
       }
     },
     "estraverse": {
@@ -1886,15 +3310,6 @@
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
       "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
     },
-    "event-emitter": {
-      "version": "0.3.5",
-      "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
-      "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
-      "requires": {
-        "d": "1.0.0",
-        "es5-ext": "0.10.39"
-      }
-    },
     "event-stream": {
       "version": "3.3.4",
       "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
@@ -1908,17 +3323,30 @@
         "split": "0.3.3",
         "stream-combiner": "0.0.4",
         "through": "2.3.8"
+      },
+      "dependencies": {
+        "split": {
+          "version": "0.3.3",
+          "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
+          "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+          "dev": true,
+          "requires": {
+            "through": "2.3.8"
+          }
+        }
       }
     },
     "events": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
-      "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
+      "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
+      "dev": true
     },
     "evp_bytestokey": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
       "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+      "dev": true,
       "requires": {
         "md5.js": "1.3.4",
         "safe-buffer": "5.1.1"
@@ -1928,6 +3356,7 @@
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
       "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+      "dev": true,
       "requires": {
         "cross-spawn": "5.1.0",
         "get-stream": "3.0.0",
@@ -1943,6 +3372,12 @@
       "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
       "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
     },
+    "exit-hook": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
+      "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=",
+      "dev": true
+    },
     "expand-brackets": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
@@ -1954,9 +3389,17 @@
         "posix-character-classes": "0.1.1",
         "regex-not": "1.0.2",
         "snapdragon": "0.8.1",
-        "to-regex": "3.0.1"
+        "to-regex": "3.0.2"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "define-property": {
           "version": "0.2.5",
           "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -2030,6 +3473,7 @@
       "version": "1.8.2",
       "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
       "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+      "dev": true,
       "requires": {
         "fill-range": "2.2.3"
       },
@@ -2038,6 +3482,7 @@
           "version": "2.2.3",
           "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
           "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+          "dev": true,
           "requires": {
             "is-number": "2.1.0",
             "isobject": "2.1.0",
@@ -2050,6 +3495,7 @@
           "version": "2.1.0",
           "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
           "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+          "dev": true,
           "requires": {
             "kind-of": "3.2.2"
           }
@@ -2058,6 +3504,7 @@
           "version": "2.1.0",
           "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
           "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+          "dev": true,
           "requires": {
             "isarray": "1.0.0"
           }
@@ -2066,6 +3513,7 @@
           "version": "3.2.2",
           "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
           "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
           "requires": {
             "is-buffer": "1.1.6"
           }
@@ -2085,7 +3533,7 @@
       "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz",
       "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=",
       "requires": {
-        "accepts": "1.3.4",
+        "accepts": "1.3.5",
         "array-flatten": "1.1.1",
         "body-parser": "1.18.2",
         "content-disposition": "0.5.2",
@@ -2117,6 +3565,14 @@
         "vary": "1.1.2"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "setprototypeof": {
           "version": "1.1.0",
           "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
@@ -2143,6 +3599,16 @@
         "parseurl": "1.3.2",
         "uid-safe": "2.1.5",
         "utils-merge": "1.0.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
       }
     },
     "extend": {
@@ -2192,7 +3658,7 @@
         "fragment-cache": "0.2.1",
         "regex-not": "1.0.2",
         "snapdragon": "0.8.1",
-        "to-regex": "3.0.1"
+        "to-regex": "3.0.2"
       },
       "dependencies": {
         "define-property": {
@@ -2219,9 +3685,9 @@
       "integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk="
     },
     "fast-deep-equal": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
-      "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8="
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+      "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
     },
     "fast-json-stable-stringify": {
       "version": "2.0.0",
@@ -2275,9 +3741,9 @@
       }
     },
     "file-loader": {
-      "version": "1.1.10",
-      "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.10.tgz",
-      "integrity": "sha512-dNnT4yJgUPtGDg0+m03kQ0b/PZi3Y12EnqYuRPNCsbYkBZc6j+fwVWy40jWzZjn5kIzQ4BLIxzJimbwAYlnPGw==",
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
+      "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
       "requires": {
         "loader-utils": "1.1.0",
         "schema-utils": "0.4.5"
@@ -2286,7 +3752,8 @@
     "filename-regex": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
-      "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY="
+      "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+      "dev": true
     },
     "fill-range": {
       "version": "4.0.0",
@@ -2323,6 +3790,14 @@
         "unpipe": "1.0.0"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "statuses": {
           "version": "1.3.1",
           "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
@@ -2330,14 +3805,22 @@
         }
       }
     },
+    "find-cache-dir": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
+      "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+      "requires": {
+        "commondir": "1.0.1",
+        "make-dir": "1.2.0",
+        "pkg-dir": "2.0.0"
+      }
+    },
     "find-up": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
-      "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
-      "dev": true,
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+      "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
       "requires": {
-        "path-exists": "2.1.0",
-        "pinkie-promise": "2.0.1"
+        "locate-path": "2.0.0"
       }
     },
     "findup-sync": {
@@ -2347,7 +3830,7 @@
       "requires": {
         "detect-file": "1.0.0",
         "is-glob": "3.1.0",
-        "micromatch": "3.1.8",
+        "micromatch": "3.1.9",
         "resolve-dir": "1.0.1"
       },
       "dependencies": {
@@ -2373,6 +3856,15 @@
         "parse-filepath": "1.0.2"
       }
     },
+    "first-chunk-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz",
+      "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=",
+      "dev": true,
+      "requires": {
+        "readable-stream": "2.3.5"
+      }
+    },
     "flagged-respawn": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz",
@@ -2390,6 +3882,21 @@
         "write": "0.2.1"
       }
     },
+    "flow-parser": {
+      "version": "0.67.0",
+      "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.67.0.tgz",
+      "integrity": "sha1-OTXa9jO7tKJxT81lIzKzHNlsDqg=",
+      "dev": true
+    },
+    "flush-write-stream": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz",
+      "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=",
+      "requires": {
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.5"
+      }
+    },
     "fmtr": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/fmtr/-/fmtr-1.1.0.tgz",
@@ -2404,13 +3911,30 @@
       "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
     },
     "for-own": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
-      "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+      "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
       "requires": {
         "for-in": "1.0.2"
       }
     },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+      "dev": true
+    },
+    "form-data": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+      "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
+      "dev": true,
+      "requires": {
+        "asynckit": "0.4.0",
+        "combined-stream": "1.0.6",
+        "mime-types": "2.1.18"
+      }
+    },
     "forwarded": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@@ -2435,21 +3959,41 @@
       "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
       "dev": true
     },
+    "from2": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+      "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+      "requires": {
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.5"
+      }
+    },
     "fs": {
       "version": "0.0.1-security",
       "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
       "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
     },
+    "fs-write-stream-atomic": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+      "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+      "requires": {
+        "graceful-fs": "4.1.11",
+        "iferr": "0.1.5",
+        "imurmurhash": "0.1.4",
+        "readable-stream": "2.3.5"
+      }
+    },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
-      "dev": true
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
     },
     "fsevents": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
       "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
+      "dev": true,
       "optional": true,
       "requires": {
         "nan": "2.9.2",
@@ -2459,11 +4003,13 @@
         "abbrev": {
           "version": "1.1.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "ajv": {
           "version": "4.11.8",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "co": "4.6.0",
@@ -2472,16 +4018,19 @@
         },
         "ansi-regex": {
           "version": "2.1.1",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "aproba": {
           "version": "1.1.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "are-we-there-yet": {
           "version": "1.1.4",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "delegates": "1.0.0",
@@ -2491,35 +4040,42 @@
         "asn1": {
           "version": "0.2.3",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "assert-plus": {
           "version": "0.2.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "asynckit": {
           "version": "0.4.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "aws-sign2": {
           "version": "0.6.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "aws4": {
           "version": "1.6.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "balanced-match": {
           "version": "0.4.2",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "bcrypt-pbkdf": {
           "version": "1.0.1",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "tweetnacl": "0.14.5"
@@ -2528,6 +4084,7 @@
         "block-stream": {
           "version": "0.0.9",
           "bundled": true,
+          "dev": true,
           "requires": {
             "inherits": "2.0.3"
           }
@@ -2535,6 +4092,7 @@
         "boom": {
           "version": "2.10.1",
           "bundled": true,
+          "dev": true,
           "requires": {
             "hoek": "2.16.3"
           }
@@ -2542,6 +4100,7 @@
         "brace-expansion": {
           "version": "1.1.7",
           "bundled": true,
+          "dev": true,
           "requires": {
             "balanced-match": "0.4.2",
             "concat-map": "0.0.1"
@@ -2549,44 +4108,53 @@
         },
         "buffer-shims": {
           "version": "1.0.0",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "caseless": {
           "version": "0.12.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "co": {
           "version": "4.6.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "code-point-at": {
           "version": "1.1.0",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "combined-stream": {
           "version": "1.0.5",
           "bundled": true,
+          "dev": true,
           "requires": {
             "delayed-stream": "1.0.0"
           }
         },
         "concat-map": {
           "version": "0.0.1",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "console-control-strings": {
           "version": "1.1.0",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "core-util-is": {
           "version": "1.0.2",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "cryptiles": {
           "version": "2.0.5",
           "bundled": true,
+          "dev": true,
           "requires": {
             "boom": "2.10.1"
           }
@@ -2594,6 +4162,7 @@
         "dashdash": {
           "version": "1.14.1",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "assert-plus": "1.0.0"
@@ -2602,6 +4171,7 @@
             "assert-plus": {
               "version": "1.0.0",
               "bundled": true,
+              "dev": true,
               "optional": true
             }
           }
@@ -2609,6 +4179,7 @@
         "debug": {
           "version": "2.6.8",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "ms": "2.0.0"
@@ -2617,25 +4188,30 @@
         "deep-extend": {
           "version": "0.4.2",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "delayed-stream": {
           "version": "1.0.0",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "delegates": {
           "version": "1.0.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "detect-libc": {
           "version": "1.0.2",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "ecc-jsbn": {
           "version": "0.1.1",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "jsbn": "0.1.1"
@@ -2644,20 +4220,24 @@
         "extend": {
           "version": "3.0.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "extsprintf": {
           "version": "1.0.2",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "forever-agent": {
           "version": "0.6.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "form-data": {
           "version": "2.1.4",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "asynckit": "0.4.0",
@@ -2667,11 +4247,13 @@
         },
         "fs.realpath": {
           "version": "1.0.0",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "fstream": {
           "version": "1.0.11",
           "bundled": true,
+          "dev": true,
           "requires": {
             "graceful-fs": "4.1.11",
             "inherits": "2.0.3",
@@ -2682,6 +4264,7 @@
         "fstream-ignore": {
           "version": "1.0.5",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "fstream": "1.0.11",
@@ -2692,6 +4275,7 @@
         "gauge": {
           "version": "2.7.4",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "aproba": "1.1.1",
@@ -2707,6 +4291,7 @@
         "getpass": {
           "version": "0.1.7",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "assert-plus": "1.0.0"
@@ -2715,6 +4300,7 @@
             "assert-plus": {
               "version": "1.0.0",
               "bundled": true,
+              "dev": true,
               "optional": true
             }
           }
@@ -2722,6 +4308,7 @@
         "glob": {
           "version": "7.1.2",
           "bundled": true,
+          "dev": true,
           "requires": {
             "fs.realpath": "1.0.0",
             "inflight": "1.0.6",
@@ -2733,16 +4320,19 @@
         },
         "graceful-fs": {
           "version": "4.1.11",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "har-schema": {
           "version": "1.0.5",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "har-validator": {
           "version": "4.2.1",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "ajv": "4.11.8",
@@ -2752,11 +4342,13 @@
         "has-unicode": {
           "version": "2.0.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "hawk": {
           "version": "3.1.3",
           "bundled": true,
+          "dev": true,
           "requires": {
             "boom": "2.10.1",
             "cryptiles": "2.0.5",
@@ -2766,11 +4358,13 @@
         },
         "hoek": {
           "version": "2.16.3",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "http-signature": {
           "version": "1.1.1",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "assert-plus": "0.2.0",
@@ -2781,6 +4375,7 @@
         "inflight": {
           "version": "1.0.6",
           "bundled": true,
+          "dev": true,
           "requires": {
             "once": "1.4.0",
             "wrappy": "1.0.2"
@@ -2788,16 +4383,19 @@
         },
         "inherits": {
           "version": "2.0.3",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "ini": {
           "version": "1.3.4",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "is-fullwidth-code-point": {
           "version": "1.0.0",
           "bundled": true,
+          "dev": true,
           "requires": {
             "number-is-nan": "1.0.1"
           }
@@ -2805,20 +4403,24 @@
         "is-typedarray": {
           "version": "1.0.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "isarray": {
           "version": "1.0.0",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "isstream": {
           "version": "0.1.2",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "jodid25519": {
           "version": "1.0.2",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "jsbn": "0.1.1"
@@ -2827,16 +4429,19 @@
         "jsbn": {
           "version": "0.1.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "json-schema": {
           "version": "0.2.3",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "json-stable-stringify": {
           "version": "1.0.1",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "jsonify": "0.0.0"
@@ -2845,16 +4450,19 @@
         "json-stringify-safe": {
           "version": "5.0.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "jsonify": {
           "version": "0.0.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "jsprim": {
           "version": "1.4.0",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "assert-plus": "1.0.0",
@@ -2866,17 +4474,20 @@
             "assert-plus": {
               "version": "1.0.0",
               "bundled": true,
+              "dev": true,
               "optional": true
             }
           }
         },
         "mime-db": {
           "version": "1.27.0",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "mime-types": {
           "version": "2.1.15",
           "bundled": true,
+          "dev": true,
           "requires": {
             "mime-db": "1.27.0"
           }
@@ -2884,17 +4495,20 @@
         "minimatch": {
           "version": "3.0.4",
           "bundled": true,
+          "dev": true,
           "requires": {
             "brace-expansion": "1.1.7"
           }
         },
         "minimist": {
           "version": "0.0.8",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "mkdirp": {
           "version": "0.5.1",
           "bundled": true,
+          "dev": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -2902,11 +4516,13 @@
         "ms": {
           "version": "2.0.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "node-pre-gyp": {
           "version": "0.6.39",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "detect-libc": "1.0.2",
@@ -2925,6 +4541,7 @@
         "nopt": {
           "version": "4.0.1",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "abbrev": "1.1.0",
@@ -2934,6 +4551,7 @@
         "npmlog": {
           "version": "4.1.0",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "are-we-there-yet": "1.1.4",
@@ -2944,21 +4562,25 @@
         },
         "number-is-nan": {
           "version": "1.0.1",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "oauth-sign": {
           "version": "0.8.2",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "object-assign": {
           "version": "4.1.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "once": {
           "version": "1.4.0",
           "bundled": true,
+          "dev": true,
           "requires": {
             "wrappy": "1.0.2"
           }
@@ -2966,16 +4588,19 @@
         "os-homedir": {
           "version": "1.0.2",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "os-tmpdir": {
           "version": "1.0.2",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "osenv": {
           "version": "0.1.4",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "os-homedir": "1.0.2",
@@ -2984,30 +4609,36 @@
         },
         "path-is-absolute": {
           "version": "1.0.1",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "performance-now": {
           "version": "0.2.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "process-nextick-args": {
           "version": "1.0.7",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "punycode": {
           "version": "1.4.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "qs": {
           "version": "6.4.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "rc": {
           "version": "1.2.1",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "deep-extend": "0.4.2",
@@ -3019,6 +4650,7 @@
             "minimist": {
               "version": "1.2.0",
               "bundled": true,
+              "dev": true,
               "optional": true
             }
           }
@@ -3026,6 +4658,7 @@
         "readable-stream": {
           "version": "2.2.9",
           "bundled": true,
+          "dev": true,
           "requires": {
             "buffer-shims": "1.0.0",
             "core-util-is": "1.0.2",
@@ -3039,6 +4672,7 @@
         "request": {
           "version": "2.81.0",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "aws-sign2": "0.6.0",
@@ -3068,32 +4702,38 @@
         "rimraf": {
           "version": "2.6.1",
           "bundled": true,
+          "dev": true,
           "requires": {
             "glob": "7.1.2"
           }
         },
         "safe-buffer": {
           "version": "5.0.1",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "semver": {
           "version": "5.3.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "set-blocking": {
           "version": "2.0.0",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "signal-exit": {
           "version": "3.0.2",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "sntp": {
           "version": "1.0.9",
           "bundled": true,
+          "dev": true,
           "requires": {
             "hoek": "2.16.3"
           }
@@ -3101,6 +4741,7 @@
         "sshpk": {
           "version": "1.13.0",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "asn1": "0.2.3",
@@ -3117,6 +4758,7 @@
             "assert-plus": {
               "version": "1.0.0",
               "bundled": true,
+              "dev": true,
               "optional": true
             }
           }
@@ -3124,6 +4766,7 @@
         "string-width": {
           "version": "1.0.2",
           "bundled": true,
+          "dev": true,
           "requires": {
             "code-point-at": "1.1.0",
             "is-fullwidth-code-point": "1.0.0",
@@ -3133,6 +4776,7 @@
         "string_decoder": {
           "version": "1.0.1",
           "bundled": true,
+          "dev": true,
           "requires": {
             "safe-buffer": "5.0.1"
           }
@@ -3140,11 +4784,13 @@
         "stringstream": {
           "version": "0.0.5",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "strip-ansi": {
           "version": "3.0.1",
           "bundled": true,
+          "dev": true,
           "requires": {
             "ansi-regex": "2.1.1"
           }
@@ -3152,11 +4798,13 @@
         "strip-json-comments": {
           "version": "2.0.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "tar": {
           "version": "2.2.1",
           "bundled": true,
+          "dev": true,
           "requires": {
             "block-stream": "0.0.9",
             "fstream": "1.0.11",
@@ -3166,6 +4814,7 @@
         "tar-pack": {
           "version": "3.4.0",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "debug": "2.6.8",
@@ -3181,6 +4830,7 @@
         "tough-cookie": {
           "version": "2.3.2",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "punycode": "1.4.1"
@@ -3189,6 +4839,7 @@
         "tunnel-agent": {
           "version": "0.6.0",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "safe-buffer": "5.0.1"
@@ -3197,25 +4848,30 @@
         "tweetnacl": {
           "version": "0.14.5",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "uid-number": {
           "version": "0.0.6",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "util-deprecate": {
           "version": "1.0.2",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         },
         "uuid": {
           "version": "3.0.1",
           "bundled": true,
+          "dev": true,
           "optional": true
         },
         "verror": {
           "version": "1.3.6",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "extsprintf": "1.0.2"
@@ -3224,6 +4880,7 @@
         "wide-align": {
           "version": "1.1.2",
           "bundled": true,
+          "dev": true,
           "optional": true,
           "requires": {
             "string-width": "1.0.2"
@@ -3231,7 +4888,8 @@
         },
         "wrappy": {
           "version": "1.0.2",
-          "bundled": true
+          "bundled": true,
+          "dev": true
         }
       }
     },
@@ -3254,23 +4912,85 @@
     "get-caller-file": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
-      "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U="
+      "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
+      "dev": true
     },
     "get-stream": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
-      "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+      "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+      "dev": true
     },
     "get-value": {
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
       "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
     },
+    "getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "1.0.0"
+      }
+    },
+    "gh-got": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz",
+      "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==",
+      "dev": true,
+      "requires": {
+        "got": "7.1.0",
+        "is-plain-obj": "1.1.0"
+      },
+      "dependencies": {
+        "got": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz",
+          "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==",
+          "dev": true,
+          "requires": {
+            "decompress-response": "3.3.0",
+            "duplexer3": "0.1.4",
+            "get-stream": "3.0.0",
+            "is-plain-obj": "1.1.0",
+            "is-retry-allowed": "1.1.0",
+            "is-stream": "1.1.0",
+            "isurl": "1.0.0",
+            "lowercase-keys": "1.0.0",
+            "p-cancelable": "0.3.0",
+            "p-timeout": "1.2.1",
+            "safe-buffer": "5.1.1",
+            "timed-out": "4.0.1",
+            "url-parse-lax": "1.0.0",
+            "url-to-options": "1.0.1"
+          }
+        },
+        "p-timeout": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz",
+          "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=",
+          "dev": true,
+          "requires": {
+            "p-finally": "1.0.0"
+          }
+        }
+      }
+    },
+    "github-username": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz",
+      "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=",
+      "dev": true,
+      "requires": {
+        "gh-got": "6.0.0"
+      }
+    },
     "glob": {
       "version": "7.1.2",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
       "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
-      "dev": true,
       "requires": {
         "fs.realpath": "1.0.0",
         "inflight": "1.0.6",
@@ -3280,10 +5000,38 @@
         "path-is-absolute": "1.0.1"
       }
     },
+    "glob-all": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz",
+      "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=",
+      "dev": true,
+      "requires": {
+        "glob": "7.1.2",
+        "yargs": "1.2.6"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "0.1.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz",
+          "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=",
+          "dev": true
+        },
+        "yargs": {
+          "version": "1.2.6",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz",
+          "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=",
+          "dev": true,
+          "requires": {
+            "minimist": "0.1.0"
+          }
+        }
+      }
+    },
     "glob-base": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
       "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+      "dev": true,
       "requires": {
         "glob-parent": "2.0.0",
         "is-glob": "2.0.1"
@@ -3293,6 +5041,7 @@
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
           "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+          "dev": true,
           "requires": {
             "is-glob": "2.0.1"
           }
@@ -3300,12 +5049,14 @@
         "is-extglob": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
+          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+          "dev": true
         },
         "is-glob": {
           "version": "2.0.1",
           "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
           "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+          "dev": true,
           "requires": {
             "is-extglob": "1.0.0"
           }
@@ -3333,6 +5084,24 @@
         }
       }
     },
+    "global": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz",
+      "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=",
+      "dev": true,
+      "requires": {
+        "min-document": "2.19.0",
+        "process": "0.5.2"
+      },
+      "dependencies": {
+        "process": {
+          "version": "0.5.2",
+          "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
+          "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=",
+          "dev": true
+        }
+      }
+    },
     "global-dirs": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
@@ -3367,29 +5136,19 @@
     "globals": {
       "version": "11.3.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz",
-      "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==",
-      "dev": true
+      "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw=="
     },
     "globby": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
-      "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
-      "dev": true,
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+      "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
       "requires": {
         "array-union": "1.0.2",
-        "arrify": "1.0.1",
+        "dir-glob": "2.0.0",
         "glob": "7.1.2",
-        "object-assign": "4.1.1",
-        "pify": "2.3.0",
-        "pinkie-promise": "2.0.1"
-      },
-      "dependencies": {
-        "pify": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
-          "dev": true
-        }
+        "ignore": "3.3.7",
+        "pify": "3.0.0",
+        "slash": "1.0.0"
       }
     },
     "good-listener": {
@@ -3434,7 +5193,7 @@
       "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.13.1.tgz",
       "integrity": "sha512-awNp3LTrQ7dJDSX3p3PBuxNDC+WFSOrWeV6+l4Xeh2PQJVOFyQ9SZPonXRz2WZc7aIxLZsf2nDZuuuc0qyEq/A==",
       "requires": {
-        "iterall": "1.2.1"
+        "iterall": "1.2.2"
       }
     },
     "graphql-extensions": {
@@ -3468,9 +5227,9 @@
       "integrity": "sha512-AmG4WGdpL1OHwnA20ouP7BVB3KnvUOvsc7+4ULWRzEunyRFUYqxrgnEf20iZnYAha8JCb7AP4WPMwWKmGT91rg==",
       "requires": {
         "apollo-link": "1.2.1",
-        "apollo-utilities": "1.0.8",
+        "apollo-utilities": "1.0.9",
         "deprecated-decorator": "0.1.6",
-        "iterall": "1.2.1",
+        "iterall": "1.2.2",
         "uuid": "3.2.1"
       }
     },
@@ -3495,6 +5254,43 @@
         "svg-pan-zoom": "3.5.3"
       }
     },
+    "grouped-queue": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz",
+      "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=",
+      "dev": true,
+      "requires": {
+        "lodash": "4.17.5"
+      }
+    },
+    "har-schema": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
+      "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
+      "dev": true
+    },
+    "har-validator": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
+      "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
+      "dev": true,
+      "requires": {
+        "ajv": "4.11.8",
+        "har-schema": "1.0.5"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "4.11.8",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
+          "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
+          "dev": true,
+          "requires": {
+            "co": "4.6.0",
+            "json-stable-stringify": "1.0.1"
+          }
+        }
+      }
+    },
     "has": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
@@ -3509,23 +5305,35 @@
       "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
       "dev": true,
       "requires": {
-        "ansi-regex": "2.1.1"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-          "dev": true
-        }
+        "ansi-regex": "2.1.1"
       }
     },
+    "has-color": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz",
+      "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=",
+      "dev": true
+    },
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+    },
+    "has-symbol-support-x": {
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
+      "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==",
       "dev": true
     },
+    "has-to-string-tag-x": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
+      "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
+      "dev": true,
+      "requires": {
+        "has-symbol-support-x": "1.4.2"
+      }
+    },
     "has-value": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
@@ -3559,6 +5367,7 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
       "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
+      "dev": true,
       "requires": {
         "inherits": "2.0.3"
       }
@@ -3567,26 +5376,56 @@
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
       "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
+      "dev": true,
       "requires": {
         "inherits": "2.0.3",
         "minimalistic-assert": "1.0.0"
       }
     },
+    "hawk": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+      "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
+      "dev": true,
+      "requires": {
+        "boom": "2.10.1",
+        "cryptiles": "2.0.5",
+        "hoek": "2.16.3",
+        "sntp": "1.0.9"
+      }
+    },
     "hmac-drbg": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
       "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+      "dev": true,
       "requires": {
         "hash.js": "1.1.3",
         "minimalistic-assert": "1.0.0",
         "minimalistic-crypto-utils": "1.0.1"
       }
     },
+    "hoek": {
+      "version": "2.16.3",
+      "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+      "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
+      "dev": true
+    },
     "hoist-non-react-statics": {
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz",
       "integrity": "sha512-6Bl6XsDT1ntE0lHbIhr4Kp2PGcleGZ66qu5Jqk8lc0Xc/IeG6gVLmwUGs/K0Us+L8VWoKgj0uWdPMataOsm31w=="
     },
+    "home-or-tmp": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
+      "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
+      "dev": true,
+      "requires": {
+        "os-homedir": "1.0.2",
+        "os-tmpdir": "1.0.2"
+      }
+    },
     "homedir-polyfill": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz",
@@ -3598,7 +5437,14 @@
     "hosted-git-info": {
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz",
-      "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg=="
+      "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==",
+      "dev": true
+    },
+    "http-cache-semantics": {
+      "version": "3.8.1",
+      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz",
+      "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==",
+      "dev": true
     },
     "http-errors": {
       "version": "1.6.2",
@@ -3618,10 +5464,30 @@
         }
       }
     },
+    "http-signature": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+      "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "0.2.0",
+        "jsprim": "1.4.1",
+        "sshpk": "1.13.1"
+      },
+      "dependencies": {
+        "assert-plus": {
+          "version": "0.2.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+          "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
+          "dev": true
+        }
+      }
+    },
     "https-browserify": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
-      "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
+      "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+      "dev": true
     },
     "iconv-lite": {
       "version": "0.4.19",
@@ -3631,13 +5497,18 @@
     "ieee754": {
       "version": "1.1.8",
       "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
-      "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q="
+      "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=",
+      "dev": true
+    },
+    "iferr": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+      "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
     },
     "ignore": {
       "version": "3.3.7",
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz",
-      "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==",
-      "dev": true
+      "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA=="
     },
     "ignore-by-default": {
       "version": "1.0.1",
@@ -3654,13 +5525,22 @@
     "imurmurhash": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
-      "dev": true
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+    },
+    "indent-string": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+      "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+      "dev": true,
+      "requires": {
+        "repeating": "2.0.1"
+      }
     },
     "indexof": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
-      "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
+      "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+      "dev": true
     },
     "inflight": {
       "version": "1.0.6",
@@ -3688,7 +5568,7 @@
       "dev": true,
       "requires": {
         "ansi-escapes": "3.0.0",
-        "chalk": "2.3.1",
+        "chalk": "2.3.2",
         "cli-cursor": "2.1.0",
         "cli-width": "2.2.0",
         "external-editor": "2.1.0",
@@ -3708,6 +5588,16 @@
       "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
       "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ="
     },
+    "into-stream": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
+      "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=",
+      "dev": true,
+      "requires": {
+        "from2": "2.3.0",
+        "p-is-promise": "1.1.0"
+      }
+    },
     "invariant": {
       "version": "2.2.3",
       "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.3.tgz",
@@ -3719,7 +5609,8 @@
     "invert-kv": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
-      "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
+      "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
+      "dev": true
     },
     "ipaddr.js": {
       "version": "1.6.0",
@@ -3746,12 +5637,14 @@
     "is-arrayish": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+      "dev": true
     },
     "is-binary-path": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
       "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+      "dev": true,
       "requires": {
         "binary-extensions": "1.11.0"
       }
@@ -3765,6 +5658,7 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
       "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+      "dev": true,
       "requires": {
         "builtin-modules": "1.1.1"
       }
@@ -3790,12 +5684,14 @@
     "is-dotfile": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
-      "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE="
+      "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+      "dev": true
     },
     "is-equal-shallow": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
       "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+      "dev": true,
       "requires": {
         "is-primitive": "2.0.0"
       }
@@ -3826,16 +5722,25 @@
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
       "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
     },
+    "is-finite": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "1.0.1"
+      }
+    },
     "is-fullwidth-code-point": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+      "dev": true
     },
     "is-glob": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
       "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
-      "dev": true,
       "requires": {
         "is-extglob": "2.1.1"
       }
@@ -3880,6 +5785,29 @@
       "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
       "dev": true
     },
+    "is-object": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
+      "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
+      "dev": true
+    },
+    "is-observable": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz",
+      "integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=",
+      "dev": true,
+      "requires": {
+        "symbol-observable": "0.2.4"
+      },
+      "dependencies": {
+        "symbol-observable": {
+          "version": "0.2.4",
+          "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz",
+          "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=",
+          "dev": true
+        }
+      }
+    },
     "is-odd": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz",
@@ -3919,6 +5847,12 @@
         "path-is-inside": "1.0.2"
       }
     },
+    "is-plain-obj": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+      "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
+      "dev": true
+    },
     "is-plain-object": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -3930,12 +5864,14 @@
     "is-posix-bracket": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
-      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q="
+      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+      "dev": true
     },
     "is-primitive": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
-      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU="
+      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+      "dev": true
     },
     "is-promise": {
       "version": "2.1.0",
@@ -3976,11 +5912,26 @@
       "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=",
       "dev": true
     },
+    "is-scoped": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz",
+      "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=",
+      "dev": true,
+      "requires": {
+        "scoped-regex": "1.0.0"
+      }
+    },
     "is-stream": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
       "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
     },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+      "dev": true
+    },
     "is-unc-path": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
@@ -3989,6 +5940,12 @@
         "unc-path-regex": "0.1.2"
       }
     },
+    "is-utf8": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+      "dev": true
+    },
     "is-windows": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@@ -4023,51 +5980,235 @@
           "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
           "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
           "requires": {
-            "encoding": "0.1.12",
-            "is-stream": "1.1.0"
+            "encoding": "0.1.12",
+            "is-stream": "1.1.0"
+          }
+        }
+      }
+    },
+    "isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+      "dev": true
+    },
+    "istextorbinary": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz",
+      "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==",
+      "dev": true,
+      "requires": {
+        "binaryextensions": "2.1.1",
+        "editions": "1.3.4",
+        "textextensions": "2.2.0"
+      }
+    },
+    "isurl": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
+      "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
+      "dev": true,
+      "requires": {
+        "has-to-string-tag-x": "1.4.1",
+        "is-object": "1.0.1"
+      }
+    },
+    "iterall": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz",
+      "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA=="
+    },
+    "js-string-escape": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
+      "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8="
+    },
+    "js-stringify": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
+      "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds="
+    },
+    "js-tokens": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
+    },
+    "js-yaml": {
+      "version": "3.11.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz",
+      "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==",
+      "dev": true,
+      "requires": {
+        "argparse": "1.0.10",
+        "esprima": "4.0.0"
+      }
+    },
+    "js2xmlparser": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
+      "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=",
+      "dev": true,
+      "requires": {
+        "xmlcreate": "1.0.2"
+      }
+    },
+    "jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+      "dev": true,
+      "optional": true
+    },
+    "jscodeshift": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.4.1.tgz",
+      "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==",
+      "dev": true,
+      "requires": {
+        "async": "1.5.2",
+        "babel-plugin-transform-flow-strip-types": "6.22.0",
+        "babel-preset-es2015": "6.24.1",
+        "babel-preset-stage-1": "6.24.1",
+        "babel-register": "6.26.0",
+        "babylon": "6.18.0",
+        "colors": "1.1.2",
+        "flow-parser": "0.67.0",
+        "lodash": "4.17.5",
+        "micromatch": "2.3.11",
+        "node-dir": "0.1.8",
+        "nomnom": "1.8.1",
+        "recast": "0.12.9",
+        "temp": "0.8.3",
+        "write-file-atomic": "1.3.4"
+      },
+      "dependencies": {
+        "arr-diff": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+          "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+          "dev": true,
+          "requires": {
+            "arr-flatten": "1.1.0"
+          }
+        },
+        "array-unique": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+          "dev": true
+        },
+        "babylon": {
+          "version": "6.18.0",
+          "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+          "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+          "dev": true
+        },
+        "braces": {
+          "version": "1.8.5",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+          "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+          "dev": true,
+          "requires": {
+            "expand-range": "1.8.2",
+            "preserve": "0.2.0",
+            "repeat-element": "1.1.2"
+          }
+        },
+        "expand-brackets": {
+          "version": "0.1.5",
+          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+          "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+          "dev": true,
+          "requires": {
+            "is-posix-bracket": "0.1.1"
+          }
+        },
+        "extglob": {
+          "version": "0.3.2",
+          "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+          "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+          "dev": true,
+          "requires": {
+            "is-extglob": "1.0.0"
+          }
+        },
+        "is-extglob": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+          "dev": true
+        },
+        "is-glob": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+          "dev": true,
+          "requires": {
+            "is-extglob": "1.0.0"
+          }
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "1.1.6"
+          }
+        },
+        "micromatch": {
+          "version": "2.3.11",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+          "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+          "dev": true,
+          "requires": {
+            "arr-diff": "2.0.0",
+            "array-unique": "0.2.1",
+            "braces": "1.8.5",
+            "expand-brackets": "0.1.5",
+            "extglob": "0.3.2",
+            "filename-regex": "2.0.1",
+            "is-extglob": "1.0.0",
+            "is-glob": "2.0.1",
+            "kind-of": "3.2.2",
+            "normalize-path": "2.1.1",
+            "object.omit": "2.0.1",
+            "parse-glob": "3.0.4",
+            "regex-cache": "0.4.4"
+          }
+        },
+        "recast": {
+          "version": "0.12.9",
+          "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz",
+          "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==",
+          "dev": true,
+          "requires": {
+            "ast-types": "0.10.1",
+            "core-js": "2.5.3",
+            "esprima": "4.0.0",
+            "private": "0.1.8",
+            "source-map": "0.6.1"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "write-file-atomic": {
+          "version": "1.3.4",
+          "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz",
+          "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "4.1.11",
+            "imurmurhash": "0.1.4",
+            "slide": "1.1.6"
           }
         }
       }
     },
-    "iterall": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.1.tgz",
-      "integrity": "sha512-XH2awY4PboL5tG5i2P7wZ2E6oet/JkmEUpUhjcroXxBUy7bPsUOXRDMAAZe+rnH2azSXboqvyDIp5n2f7GtlCQ=="
-    },
-    "js-string-escape": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
-      "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8="
-    },
-    "js-stringify": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
-      "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds="
-    },
-    "js-tokens": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
-      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
-    },
-    "js-yaml": {
-      "version": "3.10.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
-      "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
-      "dev": true,
-      "requires": {
-        "argparse": "1.0.10",
-        "esprima": "4.0.0"
-      }
-    },
-    "js2xmlparser": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
-      "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=",
-      "dev": true,
-      "requires": {
-        "xmlcreate": "1.0.2"
-      }
-    },
     "jsdoc": {
       "version": "3.5.5",
       "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz",
@@ -4080,35 +6221,96 @@
         "escape-string-regexp": "1.0.5",
         "js2xmlparser": "3.0.0",
         "klaw": "2.0.0",
-        "marked": "0.3.16",
+        "marked": "0.3.17",
         "mkdirp": "0.5.1",
         "requizzle": "0.2.1",
         "strip-json-comments": "2.0.1",
         "taffydb": "2.6.2",
         "underscore": "1.8.3"
+      },
+      "dependencies": {
+        "babylon": {
+          "version": "7.0.0-beta.19",
+          "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz",
+          "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==",
+          "dev": true
+        }
       }
     },
-    "json-loader": {
-      "version": "0.5.7",
-      "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
-      "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w=="
+    "jsesc": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz",
+      "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4="
+    },
+    "json-buffer": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+      "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
+      "dev": true
+    },
+    "json-schema": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+      "dev": true
     },
     "json-schema-traverse": {
       "version": "0.3.1",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
       "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
     },
+    "json-stable-stringify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+      "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+      "dev": true,
+      "requires": {
+        "jsonify": "0.0.0"
+      }
+    },
     "json-stable-stringify-without-jsonify": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
       "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
       "dev": true
     },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+      "dev": true
+    },
     "json5": {
       "version": "0.5.1",
       "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
       "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
     },
+    "jsonify": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+      "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+      "dev": true
+    },
+    "jsprim": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "1.0.0",
+        "extsprintf": "1.3.0",
+        "json-schema": "0.2.3",
+        "verror": "1.10.0"
+      },
+      "dependencies": {
+        "extsprintf": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+          "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+          "dev": true
+        }
+      }
+    },
     "jstransformer": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
@@ -4118,6 +6320,15 @@
         "promise": "7.3.1"
       }
     },
+    "keyv": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz",
+      "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==",
+      "dev": true,
+      "requires": {
+        "json-buffer": "3.0.0"
+      }
+    },
     "kind-of": {
       "version": "6.0.2",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
@@ -4151,10 +6362,10 @@
         "pg-connection-string": "2.0.0",
         "readable-stream": "2.3.3",
         "safe-buffer": "5.1.1",
-        "tarn": "1.1.2",
+        "tarn": "1.1.4",
         "tildify": "1.2.0",
         "uuid": "3.2.1",
-        "v8flags": "3.0.1"
+        "v8flags": "3.0.2"
       },
       "dependencies": {
         "chalk": {
@@ -4162,28 +6373,20 @@
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
           "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
           "requires": {
-            "ansi-styles": "3.2.0",
+            "ansi-styles": "3.2.1",
             "escape-string-regexp": "1.0.5",
             "supports-color": "4.5.0"
           }
         },
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
         "has-flag": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
           "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
         },
-        "pg-connection-string": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.0.0.tgz",
-          "integrity": "sha1-Pu/lmX4G2Ugh5NUC5CtqHHP434I="
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
         },
         "process-nextick-args": {
           "version": "1.0.7",
@@ -4235,6 +6438,7 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
       "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+      "dev": true,
       "requires": {
         "invert-kv": "1.0.0"
       }
@@ -4263,71 +6467,318 @@
         }
       }
     },
-    "ldapauth-fork": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/ldapauth-fork/-/ldapauth-fork-4.0.2.tgz",
-      "integrity": "sha512-YoPHsyfV6L/4SO5EMi/Jk1xUMaY+ANlR4Yp+WIsqGkWOLPKkuzRYB4s/IsdKBeb3sdwVCw+q/YN9eoa1dXmQdA==",
+    "ldapauth-fork": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/ldapauth-fork/-/ldapauth-fork-4.0.2.tgz",
+      "integrity": "sha512-YoPHsyfV6L/4SO5EMi/Jk1xUMaY+ANlR4Yp+WIsqGkWOLPKkuzRYB4s/IsdKBeb3sdwVCw+q/YN9eoa1dXmQdA==",
+      "requires": {
+        "@types/ldapjs": "1.0.3",
+        "@types/node": "7.0.55",
+        "bcryptjs": "2.4.3",
+        "ldapjs": "1.0.2",
+        "lru-cache": "4.1.1"
+      },
+      "dependencies": {
+        "@types/node": {
+          "version": "7.0.55",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.55.tgz",
+          "integrity": "sha512-diCxfWNT4g2UM9Y+BPgy4s3egcZ2qOXc0mXLauvbsBUq9SBKQfh0SmuEUEhJVFZt/p6UDsjg1s2EgfM6OSlp4g=="
+        }
+      }
+    },
+    "ldapjs": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.2.tgz",
+      "integrity": "sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk=",
+      "requires": {
+        "asn1": "0.2.3",
+        "assert-plus": "1.0.0",
+        "backoff": "2.5.0",
+        "bunyan": "1.8.12",
+        "dashdash": "1.14.1",
+        "dtrace-provider": "0.8.6",
+        "ldap-filter": "0.2.2",
+        "once": "1.4.0",
+        "vasync": "1.6.4",
+        "verror": "1.10.0"
+      }
+    },
+    "levn": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "1.1.2",
+        "type-check": "0.3.2"
+      }
+    },
+    "liftoff": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz",
+      "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=",
+      "requires": {
+        "extend": "3.0.1",
+        "findup-sync": "2.0.0",
+        "fined": "1.1.0",
+        "flagged-respawn": "1.0.0",
+        "is-plain-object": "2.0.4",
+        "object.map": "1.0.1",
+        "rechoir": "0.6.2",
+        "resolve": "1.5.0"
+      }
+    },
+    "listr": {
+      "version": "0.13.0",
+      "resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz",
+      "integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-truncate": "0.2.1",
+        "figures": "1.7.0",
+        "indent-string": "2.1.0",
+        "is-observable": "0.2.0",
+        "is-promise": "2.1.0",
+        "is-stream": "1.1.0",
+        "listr-silent-renderer": "1.1.1",
+        "listr-update-renderer": "0.4.0",
+        "listr-verbose-renderer": "0.4.1",
+        "log-symbols": "1.0.2",
+        "log-update": "1.0.2",
+        "ora": "0.2.3",
+        "p-map": "1.2.0",
+        "rxjs": "5.5.6",
+        "stream-to-observable": "0.2.0",
+        "strip-ansi": "3.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "2.2.1",
+            "escape-string-regexp": "1.0.5",
+            "has-ansi": "2.0.0",
+            "strip-ansi": "3.0.1",
+            "supports-color": "2.0.0"
+          }
+        },
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        },
+        "log-symbols": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
+          "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
+          "dev": true,
+          "requires": {
+            "chalk": "1.1.3"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "2.1.1"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "listr-silent-renderer": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz",
+      "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=",
+      "dev": true
+    },
+    "listr-update-renderer": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz",
+      "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-truncate": "0.2.1",
+        "elegant-spinner": "1.0.1",
+        "figures": "1.7.0",
+        "indent-string": "3.2.0",
+        "log-symbols": "1.0.2",
+        "log-update": "1.0.2",
+        "strip-ansi": "3.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "2.2.1",
+            "escape-string-regexp": "1.0.5",
+            "has-ansi": "2.0.0",
+            "strip-ansi": "3.0.1",
+            "supports-color": "2.0.0"
+          }
+        },
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        },
+        "indent-string": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+          "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
+          "dev": true
+        },
+        "log-symbols": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
+          "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
+          "dev": true,
+          "requires": {
+            "chalk": "1.1.3"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "2.1.1"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "listr-verbose-renderer": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz",
+      "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=",
+      "dev": true,
       "requires": {
-        "@types/ldapjs": "1.0.3",
-        "@types/node": "7.0.55",
-        "bcryptjs": "2.4.3",
-        "ldapjs": "1.0.2",
-        "lru-cache": "4.1.1"
+        "chalk": "1.1.3",
+        "cli-cursor": "1.0.2",
+        "date-fns": "1.29.0",
+        "figures": "1.7.0"
       },
       "dependencies": {
-        "@types/node": {
-          "version": "7.0.55",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.55.tgz",
-          "integrity": "sha512-diCxfWNT4g2UM9Y+BPgy4s3egcZ2qOXc0mXLauvbsBUq9SBKQfh0SmuEUEhJVFZt/p6UDsjg1s2EgfM6OSlp4g=="
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "2.2.1",
+            "escape-string-regexp": "1.0.5",
+            "has-ansi": "2.0.0",
+            "strip-ansi": "3.0.1",
+            "supports-color": "2.0.0"
+          }
+        },
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "2.1.1"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
         }
       }
     },
-    "ldapjs": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.2.tgz",
-      "integrity": "sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk=",
-      "requires": {
-        "asn1": "0.2.3",
-        "assert-plus": "1.0.0",
-        "backoff": "2.5.0",
-        "bunyan": "1.8.12",
-        "dashdash": "1.14.1",
-        "dtrace-provider": "0.8.6",
-        "ldap-filter": "0.2.2",
-        "once": "1.4.0",
-        "vasync": "1.6.4",
-        "verror": "1.10.0"
-      }
-    },
-    "levn": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
-      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "1.1.2",
-        "type-check": "0.3.2"
-      }
-    },
-    "liftoff": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz",
-      "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=",
-      "requires": {
-        "extend": "3.0.1",
-        "findup-sync": "2.0.0",
-        "fined": "1.1.0",
-        "flagged-respawn": "1.0.0",
-        "is-plain-object": "2.0.4",
-        "object.map": "1.0.1",
-        "rechoir": "0.6.2",
-        "resolve": "1.5.0"
-      }
-    },
     "load-json-file": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
       "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+      "dev": true,
       "requires": {
         "graceful-fs": "4.1.11",
         "parse-json": "2.2.0",
@@ -4338,14 +6789,67 @@
         "pify": {
           "version": "2.3.0",
           "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        }
+      }
+    },
+    "loader-fs-cache": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.1.tgz",
+      "integrity": "sha1-VuC/CL2XCLJqdltoUJhAyN7J/bw=",
+      "dev": true,
+      "requires": {
+        "find-cache-dir": "0.1.1",
+        "mkdirp": "0.5.1"
+      },
+      "dependencies": {
+        "find-cache-dir": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz",
+          "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=",
+          "dev": true,
+          "requires": {
+            "commondir": "1.0.1",
+            "mkdirp": "0.5.1",
+            "pkg-dir": "1.0.0"
+          }
+        },
+        "find-up": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+          "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+          "dev": true,
+          "requires": {
+            "path-exists": "2.1.0",
+            "pinkie-promise": "2.0.1"
+          }
+        },
+        "path-exists": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+          "dev": true,
+          "requires": {
+            "pinkie-promise": "2.0.1"
+          }
+        },
+        "pkg-dir": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz",
+          "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
+          "dev": true,
+          "requires": {
+            "find-up": "1.1.2"
+          }
         }
       }
     },
     "loader-runner": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz",
-      "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI="
+      "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=",
+      "dev": true
     },
     "loader-utils": {
       "version": "1.1.0",
@@ -4364,13 +6868,6 @@
       "requires": {
         "p-locate": "2.0.0",
         "path-exists": "3.0.0"
-      },
-      "dependencies": {
-        "path-exists": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-          "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
-        }
       }
     },
     "lodash": {
@@ -4383,6 +6880,58 @@
       "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.5.tgz",
       "integrity": "sha512-Ez3ONp3TK9gX1HYKp6IhetcVybD+2F+Yp6GS9dfH8ue6EOCEzQtQEh4K0FYWBP9qLv+lzeQAYXw+3ySfxyZqkw=="
     },
+    "log-symbols": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+      "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+      "dev": true,
+      "requires": {
+        "chalk": "2.3.2"
+      }
+    },
+    "log-update": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz",
+      "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "1.4.0",
+        "cli-cursor": "1.0.2"
+      },
+      "dependencies": {
+        "ansi-escapes": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+          "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
+          "dev": true
+        },
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        }
+      }
+    },
     "longest": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
@@ -4415,7 +6964,6 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz",
       "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==",
-      "dev": true,
       "requires": {
         "pify": "3.0.0"
       }
@@ -4458,15 +7006,16 @@
       }
     },
     "marked": {
-      "version": "0.3.16",
-      "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.16.tgz",
-      "integrity": "sha512-diLiAxHidES67uJ1P5unXBUB4CyOFwodKrctuK0U4Ogw865N9Aw4dLmY0BK0tGKOy3xvkdMGgUXPD6W9z1Ne0Q==",
+      "version": "0.3.17",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.17.tgz",
+      "integrity": "sha512-+AKbNsjZl6jFfLPwHhWmGTqE009wTKn3RTmn9K8oUKHrX/abPJjtcRtXpYB/FFrwPJRUA86LX/de3T0knkPCmQ==",
       "dev": true
     },
     "md5.js": {
       "version": "1.3.4",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
       "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+      "dev": true,
       "requires": {
         "hash-base": "3.0.4",
         "inherits": "2.0.3"
@@ -4476,6 +7025,7 @@
           "version": "3.0.4",
           "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
           "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+          "dev": true,
           "requires": {
             "inherits": "2.0.3",
             "safe-buffer": "5.1.1"
@@ -4483,31 +7033,115 @@
         }
       }
     },
-    "mdurl": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
-      "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
-    },
-    "media-typer": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
-    },
-    "mem": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
-      "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
-      "requires": {
-        "mimic-fn": "1.2.0"
-      }
-    },
+    "mdurl": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+      "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
+    },
+    "media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+    },
+    "mem": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+      "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "1.2.0"
+      }
+    },
+    "mem-fs": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz",
+      "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=",
+      "dev": true,
+      "requires": {
+        "through2": "2.0.3",
+        "vinyl": "1.2.0",
+        "vinyl-file": "2.0.0"
+      }
+    },
+    "mem-fs-editor": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-3.0.2.tgz",
+      "integrity": "sha1-3Qpuryu4prN3QAZ6pUnrUwEFr58=",
+      "dev": true,
+      "requires": {
+        "commondir": "1.0.1",
+        "deep-extend": "0.4.2",
+        "ejs": "2.5.7",
+        "glob": "7.1.2",
+        "globby": "6.1.0",
+        "mkdirp": "0.5.1",
+        "multimatch": "2.1.0",
+        "rimraf": "2.6.2",
+        "through2": "2.0.3",
+        "vinyl": "2.1.0"
+      },
+      "dependencies": {
+        "clone": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
+          "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=",
+          "dev": true
+        },
+        "clone-stats": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+          "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+          "dev": true
+        },
+        "globby": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+          "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+          "dev": true,
+          "requires": {
+            "array-union": "1.0.2",
+            "glob": "7.1.2",
+            "object-assign": "4.1.1",
+            "pify": "2.3.0",
+            "pinkie-promise": "2.0.1"
+          }
+        },
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        },
+        "replace-ext": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
+          "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
+          "dev": true
+        },
+        "vinyl": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz",
+          "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=",
+          "dev": true,
+          "requires": {
+            "clone": "2.1.1",
+            "clone-buffer": "1.0.0",
+            "clone-stats": "1.0.0",
+            "cloneable-readable": "1.0.0",
+            "remove-trailing-separator": "1.1.0",
+            "replace-ext": "1.0.0"
+          }
+        }
+      }
+    },
     "memory-fs": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
       "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+      "dev": true,
       "requires": {
         "errno": "0.1.7",
-        "readable-stream": "2.3.4"
+        "readable-stream": "2.3.5"
       }
     },
     "merge-descriptors": {
@@ -4521,9 +7155,9 @@
       "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
     },
     "micromatch": {
-      "version": "3.1.8",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.8.tgz",
-      "integrity": "sha512-/XeuOQqYg+B5kwjDWekXseSwGS7CzE0w9Gjo4Cjkf/uFitNh47NrZHAY2vp/oS2YQVfebPIdbEIvgdy+kIcAog==",
+      "version": "3.1.9",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.9.tgz",
+      "integrity": "sha512-SlIz6sv5UPaAVVFRKodKjCg48EbNoIhgetzfK/Cy0v5U52Z6zB136M8tp0UC9jM53LYbmIRihJszvvqpKkfm9g==",
       "requires": {
         "arr-diff": "4.0.0",
         "array-unique": "0.3.2",
@@ -4537,13 +7171,14 @@
         "object.pick": "1.3.0",
         "regex-not": "1.0.2",
         "snapdragon": "0.8.1",
-        "to-regex": "3.0.1"
+        "to-regex": "3.0.2"
       }
     },
     "miller-rabin": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
       "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+      "dev": true,
       "requires": {
         "bn.js": "4.11.8",
         "brorand": "1.1.0"
@@ -4570,17 +7205,35 @@
     "mimic-fn": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
+      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+      "dev": true
+    },
+    "mimic-response": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz",
+      "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=",
+      "dev": true
+    },
+    "min-document": {
+      "version": "2.19.0",
+      "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
+      "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=",
+      "dev": true,
+      "requires": {
+        "dom-walk": "0.1.1"
+      }
     },
     "minimalistic-assert": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
-      "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M="
+      "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=",
+      "dev": true
     },
     "minimalistic-crypto-utils": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
-      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+      "dev": true
     },
     "minimatch": {
       "version": "3.0.4",
@@ -4591,9 +7244,26 @@
       }
     },
     "minimist": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+    },
+    "mississippi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
+      "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
+      "requires": {
+        "concat-stream": "1.6.1",
+        "duplexify": "3.5.4",
+        "end-of-stream": "1.4.1",
+        "flush-write-stream": "1.0.2",
+        "from2": "2.3.0",
+        "parallel-transform": "1.1.0",
+        "pump": "2.0.1",
+        "pumpify": "1.4.0",
+        "stream-each": "1.2.2",
+        "through2": "2.0.3"
+      }
     },
     "mixin-deep": {
       "version": "1.3.1",
@@ -4620,19 +7290,12 @@
       "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
       "requires": {
         "minimist": "0.0.8"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "0.0.8",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
-        }
       }
     },
     "moment": {
-      "version": "2.20.1",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
-      "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==",
+      "version": "2.21.0",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz",
+      "integrity": "sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==",
       "optional": true
     },
     "morgan": {
@@ -4645,6 +7308,29 @@
         "depd": "1.1.2",
         "on-finished": "2.3.0",
         "on-headers": "1.0.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "move-concurrently": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+      "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+      "requires": {
+        "aproba": "1.2.0",
+        "copy-concurrently": "1.0.5",
+        "fs-write-stream-atomic": "1.0.10",
+        "mkdirp": "0.5.1",
+        "rimraf": "2.6.2",
+        "run-queue": "1.0.3"
       }
     },
     "ms": {
@@ -4652,6 +7338,18 @@
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
     },
+    "multimatch": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
+      "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=",
+      "dev": true,
+      "requires": {
+        "array-differ": "1.0.0",
+        "array-union": "1.0.2",
+        "arrify": "1.0.1",
+        "minimatch": "3.0.4"
+      }
+    },
     "mute-stream": {
       "version": "0.0.7",
       "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
@@ -4715,7 +7413,7 @@
         "object.pick": "1.3.0",
         "regex-not": "1.0.2",
         "snapdragon": "0.8.1",
-        "to-regex": "3.0.1"
+        "to-regex": "3.0.2"
       }
     },
     "natural-compare": {
@@ -4735,6 +7433,24 @@
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
       "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
     },
+    "neo-async": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz",
+      "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==",
+      "dev": true
+    },
+    "nice-try": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz",
+      "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==",
+      "dev": true
+    },
+    "node-dir": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz",
+      "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=",
+      "dev": true
+    },
     "node-fetch": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.0.0.tgz",
@@ -4744,6 +7460,7 @@
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
       "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==",
+      "dev": true,
       "requires": {
         "assert": "1.4.1",
         "browserify-zlib": "0.2.0",
@@ -4759,7 +7476,7 @@
         "process": "0.11.10",
         "punycode": "1.4.1",
         "querystring-es3": "0.2.1",
-        "readable-stream": "2.3.4",
+        "readable-stream": "2.3.5",
         "stream-browserify": "2.0.1",
         "stream-http": "2.8.0",
         "string_decoder": "1.0.3",
@@ -4782,20 +7499,58 @@
         "minimatch": "3.0.4",
         "pstree.remy": "1.1.0",
         "semver": "5.5.0",
-        "supports-color": "5.2.0",
+        "supports-color": "5.3.0",
         "touch": "3.1.0",
         "undefsafe": "2.0.2",
         "update-notifier": "2.3.0"
       },
       "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+        "semver": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+          "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+          "dev": true
+        }
+      }
+    },
+    "nomnom": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz",
+      "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=",
+      "dev": true,
+      "requires": {
+        "chalk": "0.4.0",
+        "underscore": "1.6.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz",
+          "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "0.4.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz",
+          "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=",
           "dev": true,
           "requires": {
-            "ms": "2.0.0"
+            "ansi-styles": "1.0.0",
+            "has-color": "0.1.7",
+            "strip-ansi": "0.1.1"
           }
+        },
+        "strip-ansi": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz",
+          "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=",
+          "dev": true
+        },
+        "underscore": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
+          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
+          "dev": true
         }
       }
     },
@@ -4812,25 +7567,47 @@
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
       "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
+      "dev": true,
       "requires": {
         "hosted-git-info": "2.5.0",
         "is-builtin-module": "1.0.0",
-        "semver": "5.5.0",
-        "validate-npm-package-license": "3.0.1"
+        "semver": "4.3.2",
+        "validate-npm-package-license": "3.0.3"
       }
     },
     "normalize-path": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
       "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+      "dev": true,
       "requires": {
         "remove-trailing-separator": "1.1.0"
       }
     },
+    "normalize-url": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
+      "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
+      "dev": true,
+      "requires": {
+        "prepend-http": "2.0.0",
+        "query-string": "5.1.0",
+        "sort-keys": "2.0.0"
+      },
+      "dependencies": {
+        "prepend-http": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+          "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+          "dev": true
+        }
+      }
+    },
     "npm-run-path": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
       "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+      "dev": true,
       "requires": {
         "path-key": "2.0.1"
       }
@@ -4838,7 +7615,14 @@
     "number-is-nan": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
-      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "dev": true
+    },
+    "oauth-sign": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+      "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
+      "dev": true
     },
     "object-assign": {
       "version": "4.1.1",
@@ -4906,6 +7690,12 @@
         }
       }
     },
+    "object-hash": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.2.0.tgz",
+      "integrity": "sha512-smRWXzkvxw72VquyZ0wggySl7PFUtoDhvhpdwgESXxUrH7vVhhp9asfup1+rVLrhsl7L45Ee1Q/l5R2Ul4MwUg==",
+      "dev": true
+    },
     "object-visit": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
@@ -4923,16 +7713,6 @@
         "array-slice": "1.1.0",
         "for-own": "1.0.0",
         "isobject": "3.0.1"
-      },
-      "dependencies": {
-        "for-own": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
-          "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
-          "requires": {
-            "for-in": "1.0.2"
-          }
-        }
       }
     },
     "object.map": {
@@ -4942,25 +7722,27 @@
       "requires": {
         "for-own": "1.0.0",
         "make-iterator": "1.0.0"
-      },
-      "dependencies": {
-        "for-own": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
-          "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
-          "requires": {
-            "for-in": "1.0.2"
-          }
-        }
       }
     },
     "object.omit": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
       "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+      "dev": true,
       "requires": {
         "for-own": "0.1.5",
         "is-extendable": "0.1.1"
+      },
+      "dependencies": {
+        "for-own": {
+          "version": "0.1.5",
+          "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+          "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+          "dev": true,
+          "requires": {
+            "for-in": "1.0.2"
+          }
+        }
       }
     },
     "object.pick": {
@@ -5013,12 +7795,94 @@
         "prelude-ls": "1.1.2",
         "type-check": "0.3.2",
         "wordwrap": "1.0.0"
+      },
+      "dependencies": {
+        "wordwrap": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+          "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+          "dev": true
+        }
+      }
+    },
+    "ora": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz",
+      "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-cursor": "1.0.2",
+        "cli-spinners": "0.1.2",
+        "object-assign": "4.1.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "2.2.1",
+            "escape-string-regexp": "1.0.5",
+            "has-ansi": "2.0.0",
+            "strip-ansi": "3.0.1",
+            "supports-color": "2.0.0"
+          }
+        },
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "2.1.1"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
       }
     },
     "os-browserify": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
-      "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
+      "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
+      "dev": true
     },
     "os-homedir": {
       "version": "1.0.2",
@@ -5029,22 +7893,57 @@
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
       "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+      "dev": true,
       "requires": {
         "execa": "0.7.0",
         "lcid": "1.0.0",
         "mem": "1.1.0"
       }
     },
+    "os-shim": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz",
+      "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=",
+      "dev": true
+    },
     "os-tmpdir": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
       "dev": true
     },
+    "p-cancelable": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz",
+      "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==",
+      "dev": true
+    },
+    "p-each-series": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz",
+      "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=",
+      "dev": true,
+      "requires": {
+        "p-reduce": "1.0.0"
+      }
+    },
     "p-finally": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
-      "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+      "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+      "dev": true
+    },
+    "p-is-promise": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
+      "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=",
+      "dev": true
+    },
+    "p-lazy": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-lazy/-/p-lazy-1.0.0.tgz",
+      "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=",
+      "dev": true
     },
     "p-limit": {
       "version": "1.2.0",
@@ -5062,6 +7961,27 @@
         "p-limit": "1.2.0"
       }
     },
+    "p-map": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+      "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+      "dev": true
+    },
+    "p-reduce": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz",
+      "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=",
+      "dev": true
+    },
+    "p-timeout": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz",
+      "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==",
+      "dev": true,
+      "requires": {
+        "p-finally": "1.0.0"
+      }
+    },
     "p-try": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
@@ -5077,6 +7997,14 @@
         "registry-auth-token": "3.3.2",
         "registry-url": "3.1.0",
         "semver": "5.5.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+          "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+          "dev": true
+        }
       }
     },
     "packet-reader": {
@@ -5087,12 +8015,24 @@
     "pako": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
-      "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg=="
+      "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==",
+      "dev": true
+    },
+    "parallel-transform": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
+      "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
+      "requires": {
+        "cyclist": "0.2.2",
+        "inherits": "2.0.3",
+        "readable-stream": "2.3.5"
+      }
     },
     "parse-asn1": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz",
       "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=",
+      "dev": true,
       "requires": {
         "asn1.js": "4.10.1",
         "browserify-aes": "1.1.1",
@@ -5115,6 +8055,7 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
       "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+      "dev": true,
       "requires": {
         "glob-base": "0.3.0",
         "is-dotfile": "1.0.3",
@@ -5125,12 +8066,14 @@
         "is-extglob": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
+          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+          "dev": true
         },
         "is-glob": {
           "version": "2.0.1",
           "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
           "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+          "dev": true,
           "requires": {
             "is-extglob": "1.0.0"
           }
@@ -5141,6 +8084,7 @@
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
       "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+      "dev": true,
       "requires": {
         "error-ex": "1.3.1"
       }
@@ -5195,7 +8139,8 @@
     "path-browserify": {
       "version": "0.0.0",
       "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
-      "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo="
+      "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
+      "dev": true
     },
     "path-dirname": {
       "version": "1.0.2",
@@ -5204,13 +8149,9 @@
       "dev": true
     },
     "path-exists": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
-      "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
-      "dev": true,
-      "requires": {
-        "pinkie-promise": "2.0.1"
-      }
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
     },
     "path-is-absolute": {
       "version": "1.0.1",
@@ -5226,7 +8167,8 @@
     "path-key": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
     },
     "path-parse": {
       "version": "1.0.5",
@@ -5252,18 +8194,11 @@
       "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
     },
     "path-type": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
-      "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+      "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
       "requires": {
-        "pify": "2.3.0"
-      },
-      "dependencies": {
-        "pify": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
-        }
+        "pify": "3.0.0"
       }
     },
     "pause": {
@@ -5284,6 +8219,7 @@
       "version": "3.0.14",
       "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
       "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
+      "dev": true,
       "requires": {
         "create-hash": "1.1.3",
         "create-hmac": "1.1.6",
@@ -5292,6 +8228,12 @@
         "sha.js": "2.4.10"
       }
     },
+    "performance-now": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
+      "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
+      "dev": true
+    },
     "pg": {
       "version": "7.4.1",
       "resolved": "https://registry.npmjs.org/pg/-/pg-7.4.1.tgz",
@@ -5307,17 +8249,17 @@
         "semver": "4.3.2"
       },
       "dependencies": {
-        "semver": {
-          "version": "4.3.2",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
-          "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
+        "pg-connection-string": {
+          "version": "0.1.3",
+          "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz",
+          "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc="
         }
       }
     },
     "pg-connection-string": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz",
-      "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc="
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.0.0.tgz",
+      "integrity": "sha1-Pu/lmX4G2Ugh5NUC5CtqHHP434I="
     },
     "pg-pool": {
       "version": "2.0.3",
@@ -5341,23 +8283,12 @@
       "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=",
       "requires": {
         "split": "1.0.1"
-      },
-      "dependencies": {
-        "split": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
-          "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
-          "requires": {
-            "through": "2.3.8"
-          }
-        }
       }
     },
     "pify": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-      "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
-      "dev": true
+      "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
     },
     "pinkie": {
       "version": "2.0.4",
@@ -5375,12 +8306,11 @@
       }
     },
     "pkg-dir": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz",
-      "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
-      "dev": true,
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+      "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
       "requires": {
-        "find-up": "1.1.2"
+        "find-up": "2.1.0"
       }
     },
     "pluralize": {
@@ -5437,12 +8367,32 @@
     "preserve": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
-      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks="
+      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+      "dev": true
+    },
+    "prettier": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.11.1.tgz",
+      "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==",
+      "dev": true
+    },
+    "pretty-bytes": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz",
+      "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=",
+      "dev": true
+    },
+    "private": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+      "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
+      "dev": true
     },
     "process": {
       "version": "0.11.10",
       "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
-      "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+      "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+      "dev": true
     },
     "process-nextick-args": {
       "version": "2.0.0",
@@ -5463,6 +8413,11 @@
         "asap": "2.0.6"
       }
     },
+    "promise-inflight": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+      "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
+    },
     "prop-types": {
       "version": "15.6.1",
       "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz",
@@ -5485,7 +8440,8 @@
     "prr": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
-      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
+      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+      "dev": true
     },
     "ps-tree": {
       "version": "1.1.0",
@@ -5514,6 +8470,7 @@
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
       "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=",
+      "dev": true,
       "requires": {
         "bn.js": "4.11.8",
         "browserify-rsa": "4.0.1",
@@ -5523,41 +8480,41 @@
       }
     },
     "pug": {
-      "version": "2.0.0-rc.4",
-      "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.0-rc.4.tgz",
-      "integrity": "sha512-SL7xovj6E2Loq9N0UgV6ynjMLW4urTFY/L/Fprhvz13Xc5vjzkjZjI1QHKq31200+6PSD8PyU6MqrtCTJj6/XA==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.0.tgz",
+      "integrity": "sha1-hS0TID1rQE71dLx/JSijXyWGyrY=",
       "requires": {
-        "pug-code-gen": "2.0.0",
-        "pug-filters": "2.1.5",
-        "pug-lexer": "3.1.0",
-        "pug-linker": "3.0.3",
-        "pug-load": "2.0.9",
-        "pug-parser": "4.0.0",
-        "pug-runtime": "2.0.3",
-        "pug-strip-comments": "1.0.2"
+        "pug-code-gen": "2.0.1",
+        "pug-filters": "3.0.0",
+        "pug-lexer": "4.0.0",
+        "pug-linker": "3.0.4",
+        "pug-load": "2.0.10",
+        "pug-parser": "4.0.1",
+        "pug-runtime": "2.0.4",
+        "pug-strip-comments": "1.0.3"
       }
     },
     "pug-attrs": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.2.tgz",
-      "integrity": "sha1-i+KyIlVo/6ddG4Zpgr/59BEa/8s=",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.3.tgz",
+      "integrity": "sha1-owlflw5kFR972tlX7vVftdeQXRU=",
       "requires": {
         "constantinople": "3.1.2",
         "js-stringify": "1.0.2",
-        "pug-runtime": "2.0.3"
+        "pug-runtime": "2.0.4"
       }
     },
     "pug-code-gen": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.0.tgz",
-      "integrity": "sha512-E4oiJT+Jn5tyEIloj8dIJQognbiNNp0i0cAJmYtQTFS0soJ917nlIuFtqVss3IXMEyQKUew3F4gIkBpn18KbVg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.1.tgz",
+      "integrity": "sha1-CVHsgyJddNjPxHan+Zolm199BQw=",
       "requires": {
         "constantinople": "3.1.2",
         "doctypes": "1.1.0",
         "js-stringify": "1.0.2",
-        "pug-attrs": "2.0.2",
+        "pug-attrs": "2.0.3",
         "pug-error": "1.3.2",
-        "pug-runtime": "2.0.3",
+        "pug-runtime": "2.0.4",
         "void-elements": "2.0.1",
         "with": "5.1.1"
       }
@@ -5568,23 +8525,23 @@
       "integrity": "sha1-U659nSm7A89WRJOgJhCfVMR/XyY="
     },
     "pug-filters": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-2.1.5.tgz",
-      "integrity": "sha512-xkw71KtrC4sxleKiq+cUlQzsiLn8pM5+vCgkChW2E6oNOzaqTSIBKIQ5cl4oheuDzvJYCTSYzRaVinMUrV4YLQ==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.0.0.tgz",
+      "integrity": "sha1-SSTwIDwd6iDH4UiuwgGJiGa3ydI=",
       "requires": {
         "clean-css": "3.4.28",
         "constantinople": "3.1.2",
         "jstransformer": "1.0.0",
         "pug-error": "1.3.2",
-        "pug-walk": "1.1.5",
+        "pug-walk": "1.1.6",
         "resolve": "1.5.0",
         "uglify-js": "2.8.29"
       }
     },
     "pug-lexer": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-3.1.0.tgz",
-      "integrity": "sha1-/QhzdtSmdbT1n4/vQiiDQ06VgaI=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.0.0.tgz",
+      "integrity": "sha1-IQwYRX7y4XYCQnQMXmR715TOwng=",
       "requires": {
         "character-parser": "2.2.0",
         "is-expression": "3.0.0",
@@ -5592,69 +8549,102 @@
       }
     },
     "pug-linker": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.3.tgz",
-      "integrity": "sha512-DCKczglCXOzJ1lr4xUj/lVHYvS+lGmR2+KTCjZjtIpdwaN7lNOoX2SW6KFX5X4ElvW+6ThwB+acSUg08UJFN5A==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.4.tgz",
+      "integrity": "sha1-3SVzKO7yUAFFKgub8wNJ5xSX6NI=",
       "requires": {
         "pug-error": "1.3.2",
-        "pug-walk": "1.1.5"
+        "pug-walk": "1.1.6"
       }
     },
     "pug-load": {
-      "version": "2.0.9",
-      "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.9.tgz",
-      "integrity": "sha512-BDdZOCru4mg+1MiZwRQZh25+NTRo/R6/qArrdWIf308rHtWA5N9kpoUskRe4H6FslaQujC+DigH9LqlBA4gf6Q==",
+      "version": "2.0.10",
+      "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.10.tgz",
+      "integrity": "sha1-y5kNZC+k9+18o1QzaKhhUsZQkgg=",
       "requires": {
         "object-assign": "4.1.1",
-        "pug-walk": "1.1.5"
+        "pug-walk": "1.1.6"
       }
     },
     "pug-parser": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-4.0.0.tgz",
-      "integrity": "sha512-ocEUFPdLG9awwFj0sqi1uiZLNvfoodCMULZzkRqILryIWc/UUlDlxqrKhKjAIIGPX/1SNsvxy63+ayEGocGhQg==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-4.0.1.tgz",
+      "integrity": "sha1-vSq99clYcet5En5GWWlduncPW4c=",
       "requires": {
         "pug-error": "1.3.2",
         "token-stream": "0.0.1"
       }
     },
     "pug-runtime": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.3.tgz",
-      "integrity": "sha1-mBYmB7D86eJU1CfzOYelrucWi9o="
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.4.tgz",
+      "integrity": "sha1-4XjhvaaKsujArPybztLFT9iM61g="
     },
     "pug-strip-comments": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.2.tgz",
-      "integrity": "sha1-0xOvoBvMN0mA4TmeI+vy65vchRM=",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.3.tgz",
+      "integrity": "sha1-8VWVkiBu3G+FMQ2s9K+0igJa9Z8=",
       "requires": {
         "pug-error": "1.3.2"
       }
     },
     "pug-walk": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.5.tgz",
-      "integrity": "sha512-rJlH1lXerCIAtImXBze3dtKq/ykZMA4rpO9FnPcIgsWcxZLOvd8zltaoeOVFyBSSqCkhhJWbEbTMga8UxWUUSA=="
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.6.tgz",
+      "integrity": "sha1-fKvNc3zb+uz7DzKvcSfrrPQjlHo="
+    },
+    "pump": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+      "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+      "requires": {
+        "end-of-stream": "1.4.1",
+        "once": "1.4.0"
+      }
+    },
+    "pumpify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz",
+      "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==",
+      "requires": {
+        "duplexify": "3.5.4",
+        "inherits": "2.0.3",
+        "pump": "2.0.1"
+      }
     },
     "punycode": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+      "dev": true
     },
     "qs": {
       "version": "6.5.1",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
       "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
     },
+    "query-string": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.0.tgz",
+      "integrity": "sha512-F3DkxxlY0AqD/rwe4YAwjRE2HjOkKW7TxsuteyrS/Jbwrxw887PqYBL4sWUJ9D/V1hmFns0SCD6FDyvlwo9RCQ==",
+      "dev": true,
+      "requires": {
+        "decode-uri-component": "0.2.0",
+        "object-assign": "4.1.1",
+        "strict-uri-encode": "1.1.0"
+      }
+    },
     "querystring": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
-      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+      "dev": true
     },
     "querystring-es3": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
-      "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+      "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+      "dev": true
     },
     "ramda": {
       "version": "0.23.0",
@@ -5670,6 +8660,7 @@
       "version": "1.1.7",
       "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
       "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+      "dev": true,
       "requires": {
         "is-number": "3.0.0",
         "kind-of": "4.0.0"
@@ -5679,6 +8670,7 @@
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
           "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+          "dev": true,
           "requires": {
             "is-buffer": "1.1.6"
           }
@@ -5689,6 +8681,7 @@
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
       "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
+      "dev": true,
       "requires": {
         "safe-buffer": "5.1.1"
       }
@@ -5697,6 +8690,7 @@
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
       "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+      "dev": true,
       "requires": {
         "randombytes": "2.0.6",
         "safe-buffer": "5.1.1"
@@ -5728,6 +8722,14 @@
         "ini": "1.3.5",
         "minimist": "1.2.0",
         "strip-json-comments": "2.0.1"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
       }
     },
     "react-css-themr": {
@@ -5801,39 +8803,58 @@
         "warning": "3.0.0"
       }
     },
+    "read-chunk": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz",
+      "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=",
+      "dev": true,
+      "requires": {
+        "pify": "3.0.0",
+        "safe-buffer": "5.1.1"
+      }
+    },
     "read-pkg": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
       "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+      "dev": true,
       "requires": {
         "load-json-file": "2.0.0",
         "normalize-package-data": "2.4.0",
         "path-type": "2.0.0"
+      },
+      "dependencies": {
+        "path-type": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+          "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+          "dev": true,
+          "requires": {
+            "pify": "2.3.0"
+          }
+        },
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        }
       }
     },
     "read-pkg-up": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
       "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+      "dev": true,
       "requires": {
         "find-up": "2.1.0",
         "read-pkg": "2.0.0"
-      },
-      "dependencies": {
-        "find-up": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-          "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
-          "requires": {
-            "locate-path": "2.0.0"
-          }
-        }
       }
     },
     "readable-stream": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz",
-      "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==",
+      "version": "2.3.5",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz",
+      "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==",
       "requires": {
         "core-util-is": "1.0.2",
         "inherits": "2.0.3",
@@ -5848,13 +8869,40 @@
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
       "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+      "dev": true,
       "requires": {
         "graceful-fs": "4.1.11",
         "minimatch": "3.0.4",
-        "readable-stream": "2.3.4",
+        "readable-stream": "2.3.5",
         "set-immediate-shim": "1.0.1"
       }
     },
+    "recast": {
+      "version": "0.14.4",
+      "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.4.tgz",
+      "integrity": "sha512-b6fRXujYf8mTIyljymL3rglje1LfuGKdD44CuKs6o1B18MmZ+mEEpD5gsaxGVABZHyPvYwPLcyBTA/SvxtiyFg==",
+      "dev": true,
+      "requires": {
+        "ast-types": "0.11.2",
+        "esprima": "4.0.0",
+        "private": "0.1.8",
+        "source-map": "0.6.1"
+      },
+      "dependencies": {
+        "ast-types": {
+          "version": "0.11.2",
+          "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.2.tgz",
+          "integrity": "sha512-aL+pcOQ+6dpWd0xrUe+Obo2CgdkFvsntkXEmzZKqEN4cR0PStF+1MBuc4V+YZsv4Q36luvyjG7F4lc+wH2bmag==",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
     "rechoir": {
       "version": "0.6.2",
       "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
@@ -5879,15 +8927,33 @@
       "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.2.0.tgz",
       "integrity": "sha1-5hWhbha0ehmlFXZhM9Hj6Zt4UuU="
     },
+    "regenerate": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz",
+      "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==",
+      "dev": true
+    },
     "regenerator-runtime": {
       "version": "0.11.1",
       "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
       "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
     },
+    "regenerator-transform": {
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
+      "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "6.26.0",
+        "babel-types": "6.26.0",
+        "private": "0.1.8"
+      }
+    },
     "regex-cache": {
       "version": "0.4.4",
       "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
       "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+      "dev": true,
       "requires": {
         "is-equal-shallow": "0.1.3"
       }
@@ -5901,6 +8967,17 @@
         "safe-regex": "1.1.0"
       }
     },
+    "regexpu-core": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+      "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+      "dev": true,
+      "requires": {
+        "regenerate": "1.3.3",
+        "regjsgen": "0.2.0",
+        "regjsparser": "0.1.5"
+      }
+    },
     "registry-auth-token": {
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz",
@@ -5920,10 +8997,34 @@
         "rc": "1.2.5"
       }
     },
+    "regjsgen": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+      "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+      "dev": true
+    },
+    "regjsparser": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+      "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+      "dev": true,
+      "requires": {
+        "jsesc": "0.5.0"
+      },
+      "dependencies": {
+        "jsesc": {
+          "version": "0.5.0",
+          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+          "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+          "dev": true
+        }
+      }
+    },
     "remove-trailing-separator": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
-      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+      "dev": true
     },
     "repeat-element": {
       "version": "1.1.2",
@@ -5935,15 +9036,70 @@
       "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
       "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
     },
+    "repeating": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+      "dev": true,
+      "requires": {
+        "is-finite": "1.0.2"
+      }
+    },
+    "replace-ext": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
+      "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
+      "dev": true
+    },
+    "request": {
+      "version": "2.81.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
+      "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
+      "dev": true,
+      "requires": {
+        "aws-sign2": "0.6.0",
+        "aws4": "1.6.0",
+        "caseless": "0.12.0",
+        "combined-stream": "1.0.6",
+        "extend": "3.0.1",
+        "forever-agent": "0.6.1",
+        "form-data": "2.1.4",
+        "har-validator": "4.2.1",
+        "hawk": "3.1.3",
+        "http-signature": "1.1.1",
+        "is-typedarray": "1.0.0",
+        "isstream": "0.1.2",
+        "json-stringify-safe": "5.0.1",
+        "mime-types": "2.1.18",
+        "oauth-sign": "0.8.2",
+        "performance-now": "0.2.0",
+        "qs": "6.4.0",
+        "safe-buffer": "5.1.1",
+        "stringstream": "0.0.5",
+        "tough-cookie": "2.3.4",
+        "tunnel-agent": "0.6.0",
+        "uuid": "3.2.1"
+      },
+      "dependencies": {
+        "qs": {
+          "version": "6.4.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
+          "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
+          "dev": true
+        }
+      }
+    },
     "require-directory": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+      "dev": true
     },
     "require-main-filename": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
-      "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
+      "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+      "dev": true
     },
     "require-uncached": {
       "version": "1.0.3",
@@ -5985,6 +9141,23 @@
         "path-parse": "1.0.5"
       }
     },
+    "resolve-cwd": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+      "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+      "dev": true,
+      "requires": {
+        "resolve-from": "3.0.0"
+      },
+      "dependencies": {
+        "resolve-from": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+          "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+          "dev": true
+        }
+      }
+    },
     "resolve-dir": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
@@ -6005,6 +9178,15 @@
       "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
       "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
     },
+    "responselike": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+      "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+      "dev": true,
+      "requires": {
+        "lowercase-keys": "1.0.0"
+      }
+    },
     "restore-cursor": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
@@ -6032,7 +9214,6 @@
       "version": "2.6.2",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
       "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
-      "dev": true,
       "requires": {
         "glob": "7.1.2"
       }
@@ -6041,6 +9222,7 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
       "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
+      "dev": true,
       "requires": {
         "hash-base": "2.0.2",
         "inherits": "2.0.3"
@@ -6055,6 +9237,20 @@
         "is-promise": "2.1.0"
       }
     },
+    "run-queue": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+      "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+      "requires": {
+        "aproba": "1.2.0"
+      }
+    },
+    "rx": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
+      "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=",
+      "dev": true
+    },
     "rx-lite": {
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
@@ -6070,6 +9266,23 @@
         "rx-lite": "4.0.8"
       }
     },
+    "rxjs": {
+      "version": "5.5.6",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz",
+      "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==",
+      "dev": true,
+      "requires": {
+        "symbol-observable": "1.0.1"
+      },
+      "dependencies": {
+        "symbol-observable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
+          "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
+          "dev": true
+        }
+      }
+    },
     "safe-buffer": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
@@ -6094,36 +9307,25 @@
       "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz",
       "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==",
       "requires": {
-        "ajv": "6.2.0",
+        "ajv": "6.2.1",
         "ajv-keywords": "3.1.0"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "6.2.0",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz",
-          "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=",
-          "requires": {
-            "fast-deep-equal": "1.0.0",
-            "fast-json-stable-stringify": "2.0.0",
-            "json-schema-traverse": "0.3.1"
-          }
-        },
-        "ajv-keywords": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz",
-          "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74="
-        }
       }
     },
+    "scoped-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz",
+      "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=",
+      "dev": true
+    },
     "select": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
       "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
     },
     "semver": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
-      "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA=="
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
+      "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
     },
     "semver-diff": {
       "version": "2.1.0",
@@ -6132,6 +9334,14 @@
       "dev": true,
       "requires": {
         "semver": "5.5.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+          "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+          "dev": true
+        }
       }
     },
     "send": {
@@ -6154,6 +9364,14 @@
         "statuses": "1.3.1"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "statuses": {
           "version": "1.3.1",
           "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
@@ -6161,6 +9379,11 @@
         }
       }
     },
+    "serialize-javascript": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.4.0.tgz",
+      "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU="
+    },
     "serve-favicon": {
       "version": "2.4.5",
       "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.4.5.tgz",
@@ -6187,7 +9410,8 @@
     "set-blocking": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+      "dev": true
     },
     "set-getter": {
       "version": "0.1.0",
@@ -6200,7 +9424,8 @@
     "set-immediate-shim": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
-      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
+      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
+      "dev": true
     },
     "set-value": {
       "version": "2.0.0",
@@ -6237,6 +9462,7 @@
       "version": "2.4.10",
       "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz",
       "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==",
+      "dev": true,
       "requires": {
         "inherits": "2.0.3",
         "safe-buffer": "5.1.1"
@@ -6246,6 +9472,7 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
       "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "dev": true,
       "requires": {
         "shebang-regex": "1.0.0"
       }
@@ -6253,12 +9480,30 @@
     "shebang-regex": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+      "dev": true
+    },
+    "shelljs": {
+      "version": "0.7.8",
+      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz",
+      "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=",
+      "dev": true,
+      "requires": {
+        "glob": "7.1.2",
+        "interpret": "1.1.0",
+        "rechoir": "0.6.2"
+      }
     },
     "signal-exit": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
-      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "dev": true
+    },
+    "slash": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="
     },
     "slice-ansi": {
       "version": "1.0.0",
@@ -6269,6 +9514,12 @@
         "is-fullwidth-code-point": "2.0.0"
       }
     },
+    "slide": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
+      "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=",
+      "dev": true
+    },
     "snapdragon": {
       "version": "0.8.1",
       "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz",
@@ -6284,6 +9535,14 @@
         "use": "2.0.2"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "define-property": {
           "version": "0.2.5",
           "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -6391,10 +9650,29 @@
         }
       }
     },
+    "sntp": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+      "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
+      "dev": true,
+      "requires": {
+        "hoek": "2.16.3"
+      }
+    },
+    "sort-keys": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
+      "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=",
+      "dev": true,
+      "requires": {
+        "is-plain-obj": "1.1.0"
+      }
+    },
     "source-list-map": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
-      "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A=="
+      "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==",
+      "dev": true
     },
     "source-map": {
       "version": "0.5.7",
@@ -6433,29 +9711,52 @@
       "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
       "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
     },
+    "spawn-sync": {
+      "version": "1.0.15",
+      "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz",
+      "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=",
+      "dev": true,
+      "requires": {
+        "concat-stream": "1.6.1",
+        "os-shim": "0.1.3"
+      }
+    },
     "spdx-correct": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
-      "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
+      "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
+      "dev": true,
       "requires": {
-        "spdx-license-ids": "1.2.2"
+        "spdx-expression-parse": "3.0.0",
+        "spdx-license-ids": "3.0.0"
       }
     },
+    "spdx-exceptions": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
+      "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
+      "dev": true
+    },
     "spdx-expression-parse": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
-      "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw="
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+      "dev": true,
+      "requires": {
+        "spdx-exceptions": "2.1.0",
+        "spdx-license-ids": "3.0.0"
+      }
     },
     "spdx-license-ids": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
-      "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc="
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz",
+      "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==",
+      "dev": true
     },
     "split": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
-      "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
-      "dev": true,
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
+      "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
       "requires": {
         "through": "2.3.8"
       }
@@ -6474,6 +9775,30 @@
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
       "dev": true
     },
+    "sshpk": {
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
+      "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
+      "dev": true,
+      "requires": {
+        "asn1": "0.2.3",
+        "assert-plus": "1.0.0",
+        "bcrypt-pbkdf": "1.0.1",
+        "dashdash": "1.14.1",
+        "ecc-jsbn": "0.1.1",
+        "getpass": "0.1.7",
+        "jsbn": "0.1.1",
+        "tweetnacl": "0.14.5"
+      }
+    },
+    "ssri": {
+      "version": "5.2.4",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.2.4.tgz",
+      "integrity": "sha512-UnEAgMZa15973iH7cUi0AHjJn1ACDIkaMyZILoqwN6yzt+4P81I8tBc5Hl+qwi5auMplZtPQsHrPBR5vJLcQtQ==",
+      "requires": {
+        "safe-buffer": "5.1.1"
+      }
+    },
     "static-extend": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
@@ -6553,9 +9878,10 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
       "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+      "dev": true,
       "requires": {
         "inherits": "2.0.3",
-        "readable-stream": "2.3.4"
+        "readable-stream": "2.3.5"
       }
     },
     "stream-combiner": {
@@ -6567,22 +9893,59 @@
         "duplexer": "0.1.1"
       }
     },
+    "stream-each": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz",
+      "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==",
+      "requires": {
+        "end-of-stream": "1.4.1",
+        "stream-shift": "1.0.0"
+      }
+    },
     "stream-http": {
       "version": "2.8.0",
       "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz",
       "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==",
+      "dev": true,
       "requires": {
         "builtin-status-codes": "3.0.0",
         "inherits": "2.0.3",
-        "readable-stream": "2.3.4",
+        "readable-stream": "2.3.5",
         "to-arraybuffer": "1.0.1",
         "xtend": "4.0.1"
       }
     },
+    "stream-shift": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+      "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
+    },
+    "stream-to-observable": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz",
+      "integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=",
+      "dev": true,
+      "requires": {
+        "any-observable": "0.2.0"
+      }
+    },
+    "strict-uri-encode": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
+      "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
+      "dev": true
+    },
+    "string-template": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz",
+      "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=",
+      "dev": true
+    },
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
       "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+      "dev": true,
       "requires": {
         "is-fullwidth-code-point": "2.0.0",
         "strip-ansi": "4.0.0"
@@ -6601,23 +9964,61 @@
         "safe-buffer": "5.1.1"
       }
     },
+    "stringstream": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+      "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
+      "dev": true
+    },
     "strip-ansi": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
       "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+      "dev": true,
       "requires": {
         "ansi-regex": "3.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        }
       }
     },
     "strip-bom": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-      "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="
+      "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+      "dev": true
+    },
+    "strip-bom-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz",
+      "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=",
+      "dev": true,
+      "requires": {
+        "first-chunk-stream": "2.0.0",
+        "strip-bom": "2.0.0"
+      },
+      "dependencies": {
+        "strip-bom": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+          "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+          "dev": true,
+          "requires": {
+            "is-utf8": "0.2.1"
+          }
+        }
+      }
     },
     "strip-eof": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
-      "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
+      "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+      "dev": true
     },
     "strip-json-comments": {
       "version": "2.0.1",
@@ -6626,10 +10027,9 @@
       "dev": true
     },
     "supports-color": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz",
-      "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==",
-      "dev": true,
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz",
+      "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==",
       "requires": {
         "has-flag": "3.0.0"
       }
@@ -6652,10 +10052,30 @@
       "requires": {
         "ajv": "5.5.2",
         "ajv-keywords": "2.1.1",
-        "chalk": "2.3.1",
+        "chalk": "2.3.2",
         "lodash": "4.17.5",
         "slice-ansi": "1.0.0",
         "string-width": "2.1.1"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "5.5.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+          "dev": true,
+          "requires": {
+            "co": "4.6.0",
+            "fast-deep-equal": "1.1.0",
+            "fast-json-stable-stringify": "2.0.0",
+            "json-schema-traverse": "0.3.1"
+          }
+        },
+        "ajv-keywords": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+          "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+          "dev": true
+        }
       }
     },
     "taffydb": {
@@ -6665,14 +10085,33 @@
       "dev": true
     },
     "tapable": {
-      "version": "0.2.8",
-      "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz",
-      "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI="
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz",
+      "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==",
+      "dev": true
     },
     "tarn": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/tarn/-/tarn-1.1.2.tgz",
-      "integrity": "sha1-IuZrUF/8bI+dE2FugsmxmjJh0xs="
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/tarn/-/tarn-1.1.4.tgz",
+      "integrity": "sha512-j4samMCQCP5+6Il9/cxCqBd3x4vvlLeVdoyGex0KixPKl4F8LpNbDSC6NDhjianZgUngElRr9UI1ryZqJDhwGg=="
+    },
+    "temp": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz",
+      "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=",
+      "dev": true,
+      "requires": {
+        "os-tmpdir": "1.0.2",
+        "rimraf": "2.2.8"
+      },
+      "dependencies": {
+        "rimraf": {
+          "version": "2.2.8",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
+          "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
+          "dev": true
+        }
+      }
     },
     "term-size": {
       "version": "1.2.0",
@@ -6689,11 +10128,26 @@
       "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
       "dev": true
     },
+    "textextensions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz",
+      "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==",
+      "dev": true
+    },
     "through": {
       "version": "2.3.8",
       "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
     },
+    "through2": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+      "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+      "requires": {
+        "readable-stream": "2.3.5",
+        "xtend": "4.0.1"
+      }
+    },
     "tildify": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz",
@@ -6712,6 +10166,7 @@
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz",
       "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==",
+      "dev": true,
       "requires": {
         "setimmediate": "1.0.5"
       }
@@ -6733,12 +10188,13 @@
     "to-arraybuffer": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
-      "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="
+      "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+      "dev": true
     },
     "to-fast-properties": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
-      "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+      "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
     },
     "to-object-path": {
       "version": "0.3.0",
@@ -6759,82 +10215,14 @@
       }
     },
     "to-regex": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz",
-      "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+      "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
       "requires": {
-        "define-property": "0.2.5",
-        "extend-shallow": "2.0.1",
-        "regex-not": "1.0.2"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "0.2.5",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-          "requires": {
-            "is-descriptor": "0.1.6"
-          }
-        },
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "requires": {
-            "is-extendable": "0.1.1"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-          "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-          "requires": {
-            "kind-of": "3.2.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "requires": {
-                "is-buffer": "1.1.6"
-              }
-            }
-          }
-        },
-        "is-data-descriptor": {
-          "version": "0.1.4",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-          "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-          "requires": {
-            "kind-of": "3.2.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "requires": {
-                "is-buffer": "1.1.6"
-              }
-            }
-          }
-        },
-        "is-descriptor": {
-          "version": "0.1.6",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-          "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-          "requires": {
-            "is-accessor-descriptor": "0.1.6",
-            "is-data-descriptor": "0.1.4",
-            "kind-of": "5.1.0"
-          }
-        },
-        "kind-of": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
-        }
+        "define-property": "2.0.2",
+        "extend-shallow": "3.0.2",
+        "regex-not": "1.0.2",
+        "safe-regex": "1.1.0"
       }
     },
     "to-regex-range": {
@@ -6860,10 +10248,41 @@
         "nopt": "1.0.10"
       }
     },
+    "tough-cookie": {
+      "version": "2.3.4",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
+      "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
+      "dev": true,
+      "requires": {
+        "punycode": "1.4.1"
+      }
+    },
+    "trim-right": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+      "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
+    },
     "tty-browserify": {
       "version": "0.0.0",
       "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
-      "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
+      "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+      "dev": true
+    },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "tweetnacl": {
+      "version": "0.14.5",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+      "dev": true,
+      "optional": true
     },
     "type-check": {
       "version": "0.3.2",
@@ -6886,8 +10305,7 @@
     "typedarray": {
       "version": "0.0.6",
       "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
-      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
-      "dev": true
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
     },
     "ua-parser-js": {
       "version": "0.7.17",
@@ -6902,24 +10320,6 @@
         "source-map": "0.5.7",
         "uglify-to-browserify": "1.0.2",
         "yargs": "3.10.0"
-      },
-      "dependencies": {
-        "camelcase": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
-          "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
-        },
-        "yargs": {
-          "version": "3.10.0",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
-          "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
-          "requires": {
-            "camelcase": "1.2.1",
-            "cliui": "2.1.0",
-            "decamelize": "1.2.0",
-            "window-size": "0.1.0"
-          }
-        }
       }
     },
     "uglify-to-browserify": {
@@ -6929,13 +10329,43 @@
       "optional": true
     },
     "uglifyjs-webpack-plugin": {
-      "version": "0.4.6",
-      "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz",
-      "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=",
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.2.tgz",
+      "integrity": "sha512-CG/NvzXfemUAm5Y4Guh5eEaJYHtkG7kKNpXEJHp9QpxsFVB5/qKvYWoMaq4sa99ccZ0hM3MK8vQV9XPZB4357A==",
+      "dev": true,
       "requires": {
-        "source-map": "0.5.7",
-        "uglify-js": "2.8.29",
-        "webpack-sources": "1.1.0"
+        "cacache": "10.0.4",
+        "find-cache-dir": "1.0.0",
+        "schema-utils": "0.4.5",
+        "serialize-javascript": "1.4.0",
+        "source-map": "0.6.1",
+        "uglify-es": "3.3.9",
+        "webpack-sources": "1.1.0",
+        "worker-farm": "1.5.4"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.13.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
+          "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "uglify-es": {
+          "version": "3.3.9",
+          "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
+          "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
+          "dev": true,
+          "requires": {
+            "commander": "2.13.0",
+            "source-map": "0.6.1"
+          }
+        }
       }
     },
     "uid-safe": {
@@ -6958,6 +10388,17 @@
       "dev": true,
       "requires": {
         "debug": "2.6.9"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
       }
     },
     "underscore": {
@@ -7015,6 +10456,22 @@
         }
       }
     },
+    "unique-filename": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz",
+      "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=",
+      "requires": {
+        "unique-slug": "2.0.0"
+      }
+    },
+    "unique-slug": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz",
+      "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=",
+      "requires": {
+        "imurmurhash": "0.1.4"
+      }
+    },
     "unique-string": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
@@ -7065,6 +10522,12 @@
         }
       }
     },
+    "untildify": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.2.tgz",
+      "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=",
+      "dev": true
+    },
     "unzip-response": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
@@ -7084,7 +10547,7 @@
       "dev": true,
       "requires": {
         "boxen": "1.3.0",
-        "chalk": "2.3.1",
+        "chalk": "2.3.2",
         "configstore": "3.1.1",
         "import-lazy": "2.1.0",
         "is-installed-globally": "0.1.0",
@@ -7103,6 +10566,7 @@
       "version": "0.11.0",
       "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
       "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+      "dev": true,
       "requires": {
         "punycode": "1.3.2",
         "querystring": "0.2.0"
@@ -7111,7 +10575,8 @@
         "punycode": {
           "version": "1.3.2",
           "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
-          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+          "dev": true
         }
       }
     },
@@ -7125,6 +10590,17 @@
         "schema-utils": "0.3.0"
       },
       "dependencies": {
+        "ajv": {
+          "version": "5.5.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+          "requires": {
+            "co": "4.6.0",
+            "fast-deep-equal": "1.1.0",
+            "fast-json-stable-stringify": "2.0.0",
+            "json-schema-traverse": "0.3.1"
+          }
+        },
         "schema-utils": {
           "version": "0.3.0",
           "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
@@ -7144,6 +10620,18 @@
         "prepend-http": "1.0.4"
       }
     },
+    "url-to-options": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
+      "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=",
+      "dev": true
+    },
+    "urlgrey": {
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz",
+      "integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=",
+      "dev": true
+    },
     "use": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz",
@@ -7219,6 +10707,7 @@
       "version": "0.10.3",
       "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
       "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+      "dev": true,
       "requires": {
         "inherits": "2.0.1"
       },
@@ -7226,7 +10715,8 @@
         "inherits": {
           "version": "2.0.1",
           "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
-          "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+          "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+          "dev": true
         }
       }
     },
@@ -7245,21 +10735,28 @@
       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
       "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA=="
     },
+    "v8-compile-cache": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz",
+      "integrity": "sha512-ejdrifsIydN1XDH7EuR2hn8ZrkRKUYF7tUcBjBy/lhrCvs2K+zRlbW9UHc0IQ9RsYFZJFqJrieoIHfkCa0DBRA==",
+      "dev": true
+    },
     "v8flags": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.1.tgz",
-      "integrity": "sha1-3Oj8N5wX2fLJ6e142JzgAFKxt2s=",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.2.tgz",
+      "integrity": "sha512-6sgSKoFw1UpUPd3cFdF7QGnrH6tDeBgW1F3v9gy8gLY0mlbiBXq8soy8aQpY6xeeCjH5K+JvC62Acp7gtl7wWA==",
       "requires": {
         "homedir-polyfill": "1.0.1"
       }
     },
     "validate-npm-package-license": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
-      "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz",
+      "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==",
+      "dev": true,
       "requires": {
-        "spdx-correct": "1.0.2",
-        "spdx-expression-parse": "1.0.4"
+        "spdx-correct": "3.0.0",
+        "spdx-expression-parse": "3.0.0"
       }
     },
     "vary": {
@@ -7295,10 +10792,53 @@
         "extsprintf": "1.2.0"
       }
     },
+    "vinyl": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
+      "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
+      "dev": true,
+      "requires": {
+        "clone": "1.0.3",
+        "clone-stats": "0.0.1",
+        "replace-ext": "0.0.1"
+      }
+    },
+    "vinyl-file": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz",
+      "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "4.1.11",
+        "pify": "2.3.0",
+        "pinkie-promise": "2.0.1",
+        "strip-bom": "2.0.0",
+        "strip-bom-stream": "2.0.0",
+        "vinyl": "1.2.0"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        },
+        "strip-bom": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+          "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+          "dev": true,
+          "requires": {
+            "is-utf8": "0.2.1"
+          }
+        }
+      }
+    },
     "vm-browserify": {
       "version": "0.0.4",
       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
       "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+      "dev": true,
       "requires": {
         "indexof": "0.0.1"
       }
@@ -7317,185 +10857,250 @@
       }
     },
     "watchpack": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz",
-      "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=",
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.5.0.tgz",
+      "integrity": "sha512-RSlipNQB1u48cq0wH/BNfCu1tD/cJ8ydFIkNYhp9o+3d+8unClkIovpW5qpFPgmL9OE48wfAnlZydXByWP82AA==",
+      "dev": true,
       "requires": {
-        "async": "2.6.0",
-        "chokidar": "1.7.0",
-        "graceful-fs": "4.1.11"
+        "chokidar": "2.0.2",
+        "graceful-fs": "4.1.11",
+        "neo-async": "2.5.0"
+      }
+    },
+    "webpack": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.1.0.tgz",
+      "integrity": "sha512-ZFYcAZ44kOT+xsS5MS2H1fQr0PJkwQdYem/d17wacDkkupzsAkBJ3hDShWHdPVvWluFs6pfhHWw/dVso1m0rsA==",
+      "dev": true,
+      "requires": {
+        "acorn": "5.5.1",
+        "acorn-dynamic-import": "3.0.0",
+        "ajv": "6.2.1",
+        "ajv-keywords": "3.1.0",
+        "chrome-trace-event": "0.1.2",
+        "enhanced-resolve": "4.0.0",
+        "eslint-scope": "3.7.1",
+        "loader-runner": "2.3.0",
+        "loader-utils": "1.1.0",
+        "memory-fs": "0.4.1",
+        "micromatch": "3.1.9",
+        "mkdirp": "0.5.1",
+        "neo-async": "2.5.0",
+        "node-libs-browser": "2.1.0",
+        "schema-utils": "0.4.5",
+        "tapable": "1.0.0",
+        "uglifyjs-webpack-plugin": "1.2.2",
+        "watchpack": "1.5.0",
+        "webpack-sources": "1.1.0"
       },
       "dependencies": {
-        "anymatch": {
-          "version": "1.3.2",
-          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
-          "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
-          "requires": {
-            "micromatch": "2.3.11",
-            "normalize-path": "2.1.1"
-          }
+        "acorn": {
+          "version": "5.5.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.1.tgz",
+          "integrity": "sha512-D/KGiCpM/VOtTMDS+wfjywEth926WUrArrzYov4N4SI7t+3y8747dPpCmmAvrm/Z3ygqMHnyPxvYYO0yTdn/nQ==",
+          "dev": true
+        }
+      }
+    },
+    "webpack-addons": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/webpack-addons/-/webpack-addons-1.1.5.tgz",
+      "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==",
+      "dev": true,
+      "requires": {
+        "jscodeshift": "0.4.1"
+      }
+    },
+    "webpack-cli": {
+      "version": "2.0.10",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.10.tgz",
+      "integrity": "sha512-PQWEOoXkhjBV4svPuESghZRc80VvDoSSRPaLiInWifDlRJgoPWpiLCFXyMLQTTaug7ApLrSEW7BcuwwY6DEv5w==",
+      "dev": true,
+      "requires": {
+        "chalk": "2.3.2",
+        "codecov": "3.0.0",
+        "cross-spawn": "6.0.5",
+        "diff": "3.5.0",
+        "enhanced-resolve": "4.0.0",
+        "glob-all": "3.1.0",
+        "global": "4.3.2",
+        "global-modules": "1.0.0",
+        "got": "8.2.0",
+        "inquirer": "5.1.0",
+        "interpret": "1.1.0",
+        "jscodeshift": "0.4.1",
+        "listr": "0.13.0",
+        "loader-utils": "1.1.0",
+        "lodash": "4.17.5",
+        "log-symbols": "2.2.0",
+        "mkdirp": "0.5.1",
+        "p-each-series": "1.0.0",
+        "p-lazy": "1.0.0",
+        "prettier": "1.11.1",
+        "recast": "0.14.4",
+        "resolve-cwd": "2.0.0",
+        "supports-color": "5.3.0",
+        "uglifyjs-webpack-plugin": "1.2.2",
+        "v8-compile-cache": "1.1.2",
+        "webpack-addons": "1.1.5",
+        "yargs": "9.0.1",
+        "yeoman-environment": "2.0.5",
+        "yeoman-generator": "github:ev1stensberg/generator#9e24fa31c85302ca1145ae34fc68b4f133251ca0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+          "dev": true
         },
-        "arr-diff": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
-          "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+        "cliui": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+          "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+          "dev": true,
           "requires": {
-            "arr-flatten": "1.1.0"
+            "string-width": "1.0.2",
+            "strip-ansi": "3.0.1",
+            "wrap-ansi": "2.1.0"
+          },
+          "dependencies": {
+            "string-width": {
+              "version": "1.0.2",
+              "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+              "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+              "dev": true,
+              "requires": {
+                "code-point-at": "1.1.0",
+                "is-fullwidth-code-point": "1.0.0",
+                "strip-ansi": "3.0.1"
+              }
+            },
+            "strip-ansi": {
+              "version": "3.0.1",
+              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+              "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+              "dev": true,
+              "requires": {
+                "ansi-regex": "2.1.1"
+              }
+            }
           }
         },
-        "array-unique": {
-          "version": "0.2.1",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
-          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
-        },
-        "braces": {
-          "version": "1.8.5",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
-          "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+        "cross-spawn": {
+          "version": "6.0.5",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+          "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+          "dev": true,
           "requires": {
-            "expand-range": "1.8.2",
-            "preserve": "0.2.0",
-            "repeat-element": "1.1.2"
+            "nice-try": "1.0.4",
+            "path-key": "2.0.1",
+            "semver": "5.5.0",
+            "shebang-command": "1.2.0",
+            "which": "1.3.0"
           }
         },
-        "chokidar": {
-          "version": "1.7.0",
-          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
-          "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+        "got": {
+          "version": "8.2.0",
+          "resolved": "https://registry.npmjs.org/got/-/got-8.2.0.tgz",
+          "integrity": "sha512-giadqJpXIwjY+ZsuWys8p2yjZGhOHiU4hiJHjS/oeCxw1u8vANQz3zPlrxW2Zw/siCXsSMI3hvzWGcnFyujyAg==",
+          "dev": true,
           "requires": {
-            "anymatch": "1.3.2",
-            "async-each": "1.0.1",
-            "fsevents": "1.1.3",
-            "glob-parent": "2.0.0",
-            "inherits": "2.0.3",
-            "is-binary-path": "1.0.1",
-            "is-glob": "2.0.1",
-            "path-is-absolute": "1.0.1",
-            "readdirp": "2.1.0"
+            "@sindresorhus/is": "0.7.0",
+            "cacheable-request": "2.1.4",
+            "decompress-response": "3.3.0",
+            "duplexer3": "0.1.4",
+            "get-stream": "3.0.0",
+            "into-stream": "3.1.0",
+            "is-retry-allowed": "1.1.0",
+            "isurl": "1.0.0",
+            "lowercase-keys": "1.0.0",
+            "mimic-response": "1.0.0",
+            "p-cancelable": "0.3.0",
+            "p-timeout": "2.0.1",
+            "pify": "3.0.0",
+            "safe-buffer": "5.1.1",
+            "timed-out": "4.0.1",
+            "url-parse-lax": "3.0.0",
+            "url-to-options": "1.0.1"
           }
         },
-        "expand-brackets": {
-          "version": "0.1.5",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
-          "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+        "inquirer": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.1.0.tgz",
+          "integrity": "sha512-kn7N70US1MSZHZHSGJLiZ7iCwwncc7b0gc68YtlX29OjI3Mp0tSVV+snVXpZ1G+ONS3Ac9zd1m6hve2ibLDYfA==",
+          "dev": true,
           "requires": {
-            "is-posix-bracket": "0.1.1"
+            "ansi-escapes": "3.0.0",
+            "chalk": "2.3.2",
+            "cli-cursor": "2.1.0",
+            "cli-width": "2.2.0",
+            "external-editor": "2.1.0",
+            "figures": "2.0.0",
+            "lodash": "4.17.5",
+            "mute-stream": "0.0.7",
+            "run-async": "2.3.0",
+            "rxjs": "5.5.6",
+            "string-width": "2.1.1",
+            "strip-ansi": "4.0.0",
+            "through": "2.3.8"
           }
         },
-        "extglob": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
-          "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
           "requires": {
-            "is-extglob": "1.0.0"
+            "number-is-nan": "1.0.1"
           }
         },
-        "glob-parent": {
+        "prepend-http": {
           "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
-          "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
-          "requires": {
-            "is-glob": "2.0.1"
-          }
-        },
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "requires": {
-            "is-extglob": "1.0.0"
-          }
+          "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+          "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+          "dev": true
         },
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "requires": {
-            "is-buffer": "1.1.6"
-          }
+        "semver": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+          "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+          "dev": true
         },
-        "micromatch": {
-          "version": "2.3.11",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
-          "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
-          "requires": {
-            "arr-diff": "2.0.0",
-            "array-unique": "0.2.1",
-            "braces": "1.8.5",
-            "expand-brackets": "0.1.5",
-            "extglob": "0.3.2",
-            "filename-regex": "2.0.1",
-            "is-extglob": "1.0.0",
-            "is-glob": "2.0.1",
-            "kind-of": "3.2.2",
-            "normalize-path": "2.1.1",
-            "object.omit": "2.0.1",
-            "parse-glob": "3.0.4",
-            "regex-cache": "0.4.4"
-          }
-        }
-      }
-    },
-    "webpack": {
-      "version": "3.11.0",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz",
-      "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==",
-      "requires": {
-        "acorn": "5.4.1",
-        "acorn-dynamic-import": "2.0.2",
-        "ajv": "6.1.1",
-        "ajv-keywords": "3.1.0",
-        "async": "2.6.0",
-        "enhanced-resolve": "3.4.1",
-        "escope": "3.6.0",
-        "interpret": "1.1.0",
-        "json-loader": "0.5.7",
-        "json5": "0.5.1",
-        "loader-runner": "2.3.0",
-        "loader-utils": "1.1.0",
-        "memory-fs": "0.4.1",
-        "mkdirp": "0.5.1",
-        "node-libs-browser": "2.1.0",
-        "source-map": "0.5.7",
-        "supports-color": "4.5.0",
-        "tapable": "0.2.8",
-        "uglifyjs-webpack-plugin": "0.4.6",
-        "watchpack": "1.4.0",
-        "webpack-sources": "1.1.0",
-        "yargs": "8.0.2"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "6.1.1",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.1.1.tgz",
-          "integrity": "sha1-l41Zf7wrfQ5aXD3esUmmgvKr+g4=",
+        "url-parse-lax": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+          "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+          "dev": true,
           "requires": {
-            "fast-deep-equal": "1.0.0",
-            "fast-json-stable-stringify": "2.0.0",
-            "json-schema-traverse": "0.3.1"
+            "prepend-http": "2.0.0"
           }
         },
-        "ajv-keywords": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz",
-          "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74="
-        },
-        "has-flag": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
-          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+        "y18n": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+          "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+          "dev": true
         },
-        "supports-color": {
-          "version": "4.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
-          "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+        "yargs": {
+          "version": "9.0.1",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz",
+          "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=",
+          "dev": true,
           "requires": {
-            "has-flag": "2.0.0"
+            "camelcase": "4.1.0",
+            "cliui": "3.2.0",
+            "decamelize": "1.2.0",
+            "get-caller-file": "1.0.2",
+            "os-locale": "2.1.0",
+            "read-pkg-up": "2.0.0",
+            "require-directory": "2.1.1",
+            "require-main-filename": "1.0.1",
+            "set-blocking": "2.0.0",
+            "string-width": "2.1.1",
+            "which-module": "2.0.0",
+            "y18n": "3.2.1",
+            "yargs-parser": "7.0.0"
           }
         }
       }
@@ -7503,12 +11108,14 @@
     "webpack-node-externals": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-1.6.0.tgz",
-      "integrity": "sha1-Iyxi7GCSsQBjWj0p2DwXRxKN+b0="
+      "integrity": "sha1-Iyxi7GCSsQBjWj0p2DwXRxKN+b0=",
+      "dev": true
     },
     "webpack-sources": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
       "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==",
+      "dev": true,
       "requires": {
         "source-list-map": "2.0.0",
         "source-map": "0.6.1"
@@ -7517,7 +11124,8 @@
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
         }
       }
     },
@@ -7537,7 +11145,8 @@
     "which-module": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
-      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+      "dev": true
     },
     "widest-line": {
       "version": "2.0.0",
@@ -7560,39 +11169,38 @@
       "requires": {
         "acorn": "3.3.0",
         "acorn-globals": "3.1.0"
-      },
-      "dependencies": {
-        "acorn": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-          "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
-        }
       }
     },
     "wordwrap": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
-      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
-      "dev": true
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+      "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
+    },
+    "worker-farm": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.5.4.tgz",
+      "integrity": "sha512-ITyClEvcfv0ozqJl1vmWFWhvI+OIrkbInYqkEPE50wFPXj8J9Gd3FYf8+CkZJXJJsQBYe+2DvmoK9Zhx5w8W+w==",
+      "dev": true,
+      "requires": {
+        "errno": "0.1.7",
+        "xtend": "4.0.1"
+      }
     },
     "wrap-ansi": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
       "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+      "dev": true,
       "requires": {
         "string-width": "1.0.2",
         "strip-ansi": "3.0.1"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
-        },
         "is-fullwidth-code-point": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
           "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
           "requires": {
             "number-is-nan": "1.0.1"
           }
@@ -7601,6 +11209,7 @@
           "version": "1.0.2",
           "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
           "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+          "dev": true,
           "requires": {
             "code-point-at": "1.1.0",
             "is-fullwidth-code-point": "1.0.0",
@@ -7611,6 +11220,7 @@
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
           "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
           "requires": {
             "ansi-regex": "2.1.1"
           }
@@ -7660,9 +11270,9 @@
       "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
     },
     "y18n": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
-      "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
     },
     "yallist": {
       "version": "2.1.2",
@@ -7670,78 +11280,352 @@
       "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
     },
     "yargs": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz",
-      "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=",
+      "version": "3.10.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+      "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
       "requires": {
-        "camelcase": "4.1.0",
-        "cliui": "3.2.0",
+        "camelcase": "1.2.1",
+        "cliui": "2.1.0",
         "decamelize": "1.2.0",
-        "get-caller-file": "1.0.2",
-        "os-locale": "2.1.0",
+        "window-size": "0.1.0"
+      }
+    },
+    "yargs-parser": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
+      "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
+      "dev": true,
+      "requires": {
+        "camelcase": "4.1.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+          "dev": true
+        }
+      }
+    },
+    "yeoman-environment": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.0.5.tgz",
+      "integrity": "sha512-6/W7/B54OPHJXob0n0+pmkwFsirC8cokuQkPSmT/D0lCcSxkKtg/BA6ZnjUBIwjuGqmw3DTrT4en++htaUju5g==",
+      "dev": true,
+      "requires": {
+        "chalk": "2.3.2",
+        "debug": "3.1.0",
+        "diff": "3.5.0",
+        "escape-string-regexp": "1.0.5",
+        "globby": "6.1.0",
+        "grouped-queue": "0.3.3",
+        "inquirer": "3.3.0",
+        "is-scoped": "1.0.0",
+        "lodash": "4.17.5",
+        "log-symbols": "2.2.0",
+        "mem-fs": "1.1.3",
+        "text-table": "0.2.0",
+        "untildify": "3.0.2"
+      },
+      "dependencies": {
+        "globby": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+          "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+          "dev": true,
+          "requires": {
+            "array-union": "1.0.2",
+            "glob": "7.1.2",
+            "object-assign": "4.1.1",
+            "pify": "2.3.0",
+            "pinkie-promise": "2.0.1"
+          }
+        },
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        }
+      }
+    },
+    "yeoman-generator": {
+      "version": "github:ev1stensberg/generator#9e24fa31c85302ca1145ae34fc68b4f133251ca0",
+      "dev": true,
+      "requires": {
+        "async": "2.6.0",
+        "chalk": "1.1.3",
+        "cli-table": "0.3.1",
+        "cross-spawn": "5.1.0",
+        "dargs": "5.1.0",
+        "dateformat": "2.2.0",
+        "debug": "2.6.9",
+        "detect-conflict": "1.0.1",
+        "error": "7.0.2",
+        "find-up": "2.1.0",
+        "github-username": "4.1.0",
+        "istextorbinary": "2.2.1",
+        "lodash": "4.17.5",
+        "mem-fs-editor": "3.0.2",
+        "minimist": "1.2.0",
+        "mkdirp": "0.5.1",
+        "pretty-bytes": "4.0.2",
+        "read-chunk": "2.1.0",
         "read-pkg-up": "2.0.0",
-        "require-directory": "2.1.1",
-        "require-main-filename": "1.0.1",
-        "set-blocking": "2.0.0",
-        "string-width": "2.1.1",
-        "which-module": "2.0.0",
-        "y18n": "3.2.1",
-        "yargs-parser": "7.0.0"
+        "rimraf": "2.6.2",
+        "run-async": "2.3.0",
+        "shelljs": "0.7.8",
+        "text-table": "0.2.0",
+        "through2": "2.0.3",
+        "yeoman-environment": "1.6.6"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+        "ansi-escapes": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+          "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
+          "dev": true
         },
-        "cliui": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
-          "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "async": {
+          "version": "2.6.0",
+          "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
+          "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
+          "dev": true,
+          "requires": {
+            "lodash": "4.17.5"
+          }
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "2.2.1",
+            "escape-string-regexp": "1.0.5",
+            "has-ansi": "2.0.0",
+            "strip-ansi": "3.0.1",
+            "supports-color": "2.0.0"
+          }
+        },
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "diff": {
+          "version": "2.2.3",
+          "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz",
+          "integrity": "sha1-YOr9DSjukG5Oj/ClLBIpUhAzv5k=",
+          "dev": true
+        },
+        "external-editor": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-1.1.1.tgz",
+          "integrity": "sha1-Etew24UPf/fnCBuvQAVwAGDEYAs=",
+          "dev": true,
+          "requires": {
+            "extend": "3.0.1",
+            "spawn-sync": "1.0.15",
+            "tmp": "0.0.29"
+          }
+        },
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        },
+        "glob": {
+          "version": "6.0.4",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
+          "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
+          "dev": true,
+          "requires": {
+            "inflight": "1.0.6",
+            "inherits": "2.0.3",
+            "minimatch": "3.0.4",
+            "once": "1.4.0",
+            "path-is-absolute": "1.0.1"
+          }
+        },
+        "globby": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/globby/-/globby-4.1.0.tgz",
+          "integrity": "sha1-CA9UVJ7BuCpsYOYx/ILhIR2+lfg=",
+          "dev": true,
+          "requires": {
+            "array-union": "1.0.2",
+            "arrify": "1.0.1",
+            "glob": "6.0.4",
+            "object-assign": "4.1.1",
+            "pify": "2.3.0",
+            "pinkie-promise": "2.0.1"
+          }
+        },
+        "inquirer": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-1.2.3.tgz",
+          "integrity": "sha1-TexvMvN+97sLLtPx0aXD9UUHSRg=",
+          "dev": true,
           "requires": {
+            "ansi-escapes": "1.4.0",
+            "chalk": "1.1.3",
+            "cli-cursor": "1.0.2",
+            "cli-width": "2.2.0",
+            "external-editor": "1.1.1",
+            "figures": "1.7.0",
+            "lodash": "4.17.5",
+            "mute-stream": "0.0.6",
+            "pinkie-promise": "2.0.1",
+            "run-async": "2.3.0",
+            "rx": "4.1.0",
             "string-width": "1.0.2",
             "strip-ansi": "3.0.1",
-            "wrap-ansi": "2.1.0"
-          },
-          "dependencies": {
-            "string-width": {
-              "version": "1.0.2",
-              "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-              "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-              "requires": {
-                "code-point-at": "1.1.0",
-                "is-fullwidth-code-point": "1.0.0",
-                "strip-ansi": "3.0.1"
-              }
-            }
+            "through": "2.3.8"
           }
         },
         "is-fullwidth-code-point": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
           "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
           "requires": {
             "number-is-nan": "1.0.1"
           }
         },
+        "log-symbols": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
+          "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
+          "dev": true,
+          "requires": {
+            "chalk": "1.1.3"
+          }
+        },
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        },
+        "mute-stream": {
+          "version": "0.0.6",
+          "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz",
+          "integrity": "sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s=",
+          "dev": true
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+          "dev": true,
+          "requires": {
+            "code-point-at": "1.1.0",
+            "is-fullwidth-code-point": "1.0.0",
+            "strip-ansi": "3.0.1"
+          }
+        },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
           "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
           "requires": {
             "ansi-regex": "2.1.1"
           }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        },
+        "tmp": {
+          "version": "0.0.29",
+          "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz",
+          "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=",
+          "dev": true,
+          "requires": {
+            "os-tmpdir": "1.0.2"
+          }
+        },
+        "untildify": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz",
+          "integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=",
+          "dev": true,
+          "requires": {
+            "os-homedir": "1.0.2"
+          }
+        },
+        "yeoman-environment": {
+          "version": "1.6.6",
+          "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-1.6.6.tgz",
+          "integrity": "sha1-zYX6Z9FWBg5EDXgH1+988NLR1nE=",
+          "dev": true,
+          "requires": {
+            "chalk": "1.1.3",
+            "debug": "2.6.9",
+            "diff": "2.2.3",
+            "escape-string-regexp": "1.0.5",
+            "globby": "4.1.0",
+            "grouped-queue": "0.3.3",
+            "inquirer": "1.2.3",
+            "lodash": "4.17.5",
+            "log-symbols": "1.0.2",
+            "mem-fs": "1.1.3",
+            "text-table": "0.2.0",
+            "untildify": "2.1.0"
+          }
         }
       }
     },
-    "yargs-parser": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
-      "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
-      "requires": {
-        "camelcase": "4.1.0"
-      }
-    },
     "zen-observable": {
       "version": "0.7.1",
       "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.7.1.tgz",
diff --git a/package.json b/package.json
index cd95995964c78a2258e982a934fd227fbba57a7e..24dfb2b2aed2d21b3231fa116c3e26d58e7d74ba 100644
--- a/package.json
+++ b/package.json
@@ -4,14 +4,16 @@
   "description": "Backend of sigma, the new Frankiz",
   "main": "index.js",
   "dependencies": {
+    "babel-eslint": "^8.2.2",
     "body-parser": "^1.18.2",
     "colors": "^1.1.2",
     "connect-ensure-login": "^0.1.1",
     "connect-flash": "^0.1.1",
+    "copy-webpack-plugin": "^4.5.0",
     "cors": "^2.8.4",
     "express": "^4.16.2",
     "express-session": "^1.15.6",
-    "file-loader": "^1.1.10",
+    "file-loader": "^1.1.11",
     "fs": "0.0.1-security",
     "fuse.js": "^3.2.0",
     "graphql": "^0.13.1",
@@ -21,31 +23,34 @@
     "knex": "^0.14.4",
     "ldap-escape": "^1.1.5",
     "ldapjs": "^1.0.2",
+    "lodash": "^4.17.5",
     "morgan": "^1.9.0",
     "passport": "^0.4.0",
     "passport-ldapauth": "^2.0.0",
     "pg": "^7.4.1",
     "pug": "^2.0.0-rc.4",
     "serve-favicon": "^2.4.5",
-    "url-loader": "^0.6.2",
-    "webpack": "^3.11.0",
-    "webpack-node-externals": "^1.6.0"
+    "url-loader": "^0.6.2"
   },
   "devDependencies": {
-    "eslint": "^4.18.1",
+    "eslint": "^4.18.2",
     "eslint-config-standard": "^11.0.0",
+    "eslint-loader": "^2.0.0",
     "eslint-plugin-import": "^2.9.0",
     "eslint-plugin-node": "^6.0.1",
     "eslint-plugin-promise": "^3.6.0",
     "eslint-plugin-standard": "^3.0.1",
     "jsdoc": "^3.5.5",
-    "nodemon": "^1.17.1"
+    "nodemon": "^1.17.1",
+    "webpack": "^4.1.0",
+    "webpack-cli": "^2.0.10",
+    "webpack-node-externals": "^1.6.0"
   },
   "scripts": {
     "start": "node build/bundle.js",
     "lint": "eslint src/",
-    "build": "webpack",
-    "watch": "webpack --watch",
+    "build": "webpack --mode development",
+    "watch": "webpack --watch --mode development",
     "doc": "jsdoc -c configfile_doc.json",
     "test": "nodemon --watch build build/bundle.js"
   },
diff --git a/sigma-back-dev.service b/sigma-back-dev.service
index 46874305bf25d714ce7152bae87ebc0d2ff3aa66..7ed779ab3919ef391ea7d80090b0d2b5acdf6d50 100644
--- a/sigma-back-dev.service
+++ b/sigma-back-dev.service
@@ -1,12 +1,12 @@
 [Unit]
-Description=Sigma-back
+Description=Sigma-back-dev
 Wants=network-online.target
 After=network-online.target
 
 [Service]
 Environment=NODE_ENV=development
-WorkingDirectory=/opt/sigma-back
-ExecStart=node app.js
+WorkingDirectory=/opt/sigma-back-dev
+ExecStart=node build/bundle.js
 Restart=always
 
 [Install]
diff --git a/src/admin_view/admin_router.js b/src/admin_view/admin_router.js
index 5583cfac38e44a843d15f1e73838fcc9b62d332c..ad03575f749265935380b3c33cc8c0742b2eb4d7 100644
--- a/src/admin_view/admin_router.js
+++ b/src/admin_view/admin_router.js
@@ -1,7 +1,6 @@
 /**
  * @file Ce fichier définit le routage d'URL au sein de l'interface du _backend_.
- * 
- * Il définit la page de connexion `/`, le panneau administrateur `/admin` et l'API REST (`/db/:table?`)
+ * Il définit la page de connexion `/`, le panneau administrateur `/admin` et l'API REST \(`/db/:table?`)
  * permettant de consulter la base de donnée interne à Sigma, via des requêtes construites avec Knex.
  * @author manifold
  */
@@ -14,21 +13,24 @@ const router = express.Router();
 
 let port = process.env.PORT || 3000;
 
+
+/**
+ * @description Le login se fait en POST. Faire un GET à la racine / renvoie sur
+ * /login ou sur /admin selon que l'utilisateur est connecté ou non.
+ */
+
 router.get('/', function (req, res) {
+    console.log('Redirecting to admin page...');
+    res.redirect('/admin');
+});
+
+router.get('/login', function (req, res) {
     console.log('Connecting to ' + req.url);
     req.flash('failureFlash', 'Invalid username or password.');
     res.render('login', { title: 'Login', port: port, 
         errorMessage: req.flash('error') });
 });
 
-/**
- * @description Le login se fait en POST. Faire un GET à /login renvoie à la racine /
- */
-router.get('/login', function(req,res) {
-    console.log('Redirecting to home...');
-    res.redirect('/');
-});
-
 router.get('/admin',
     ensureLoggedIn('/login'),
     function (req, res) {
@@ -52,8 +54,9 @@ router.get('/admin',
 router.post('/login', 
     passport.authenticate('ldapauth', {
         successRedirect: '/admin',
-        failureRedirect: '/',
+        failureRedirect: '/login',
         failureFlash: true
+    }
     // on a besoin de faire un callback apres le passport.authenticate car
     // on souhaite garde l'information user.dn et body.password qq part.
     // TODO: essayer de garder ces informations plus proprement...
@@ -70,7 +73,8 @@ router.post('/login',
         }
     }
     */
-    }));
+    )
+);
 
 router.post('/logout', function (req, res) {
     req.logout();
diff --git a/src/graphql/connectors/connectors.js b/src/graphql/connectors/connectors.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ec269227baf0f12b917e1d97ea96d24d83f5362
--- /dev/null
+++ b/src/graphql/connectors/connectors.js
@@ -0,0 +1,620 @@
+/**
+ * @file Fonctions pour interagir avec la BDD sigma et le LDAP.
+ * @author akka vodol
+ */
+import knex from '../../../db/knex_router';
+import { renseignerSurUtilisateur, repliquerTOLdesIds, 
+    listerGroupes, listerMembres, listerAdministrateurs 
+} from '../../ldap/ldap_data';
+import { exportAllDeclaration } from 'babel-types';
+import * as selectors from './selectors';
+import * as list_selectors from './list_selectors';
+export { renseignerSurUtilisateur, repliquerTOLdesIds, listerMembres };
+
+/*
+    Le tag @rights et la gestion des authorisations
+
+    Le système GraphQL est pensé comme l'interface par laquelle les utilisateurs 
+    intéragissent avec sigma, les graphismes en moins.
+    Pour cette raison, et pour des questions de sécurité, il faut partir du principe que
+    l'utilisateir peut rédiger n'importe quelle requête, et que c'est au niveau des resolvers
+    que la sécurité ce déroule. C'est dans cette optique que j'utilise le tag @rights
+
+    Commençons par un rappel sur le fonctionnement des droits. 
+    Chaque utilisateur a un certain niveau de droit sur chaque groupe. Ce niveau de droit indique
+    ce qu'il a le droit de savoir et de faire. Chaque niveau est inclu dans les niveaus supérieur.
+    Les différends niveaux sont :
+    none - aucun droit
+    viewer : l'utilisateur a visibilité sur le groupe. Il sait que le groupe existe, et a accès à un certain nombre d'infos.
+    member : l'utilisateur est membre du groupe
+    speaker : l'utilisateur peut parler au nom du groupe. Il a le droit de publier des annonces et d'organiser des évènements
+    admin : l'utilisateur a tous les droits sur le groupe
+
+    Certaines fonctions de connectors effectuent des vérifications d'authorisations avant 
+    de renvoyer une réponse, d'autres non. Pour être sur qu'on ne renvoie jamais de réponse
+    sans avoir au préalable éffectué les bonnes vérifications, chaque fonction possède dans sa
+    description un attribut droit, qui décrit les droits que fournit cette fonction.
+
+    La valeur de @rights peut être :
+    super - la fonction n'effectue aucune vérification, et renvoie le resultat demandé
+    admin( groupUID ) - la fonction ne fait que ce qu'un admin du groupe indiqué aurait le droit de faire
+    speaker( groupUID ), member( groupUID ), veiwer( groupUID ) - même chose
+    user - la fonction ne fait que ce que l'utiliateur a le droit de faire (vérifications via l'argument user)
+
+    La procédure a suivre est la suivante : quand une fonction possède un certain niveau de droit, 
+    elle ne peut appeler une fonction possédant un niveau de droit plus large que si 
+    1 ) on a au préalable vérifié que l'utilisateur possédait effectivement ces droits. 
+    ou
+    2 ) on s'est assuré que l'opération effectuée par cet appel particulier de la fonction était dans les droits
+    de l'utilisateur
+
+    Les resolvers de base de mutation et query ont des droits user.
+
+    Les fonctions qui ne modifient pas la BDD et ne renvoient pas de données sur la BDD n'ont pas de rights.
+*/
+
+
+
+
+/**
+ * @summary Génère une promise.
+ * @function
+ * @desc Les fonctions ici sont toutes supposées renvoyer une promise. 
+ * Si on veut renvoyer une valeur directement, cette fonction permet de construire 
+ * une Promise qui renvoie cette valeur facilement.
+ * @arg {Object} val - La valeur qu'on veut renvoyer.
+ * @return {Promise(Object)} Une promise qui renvoi val
+ */
+const quickPromise = (val) => {
+    return new Promise( (resolve, reject) => {
+        resolve(val);
+    });
+};
+
+
+
+/**
+ * @summary teste si un utilisateur a des droits
+ * @desc Cette fonction effectue une requête knex. Elle gère l'arête de parenté.
+ * @arg {Object} user - Objet contenant un attribut `uid` de type `string`. 
+ * User représente l'utilisateur qui a effectué la requête. 
+ * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire.
+ * rights user
+ */
+export async function hasAdminRights(user, groupUID){
+    let adminList = await list_selectors.usersWithAdminRights(user, groupUID);
+    return (typeof adminList != "undefined" && adminList.indexOf(user.uid) != -1);
+}
+
+/**
+ * @summary Renvoie le nom de la table dans laquelle il faut chercher en fonction de ce qu'on veut
+ * @desc a remplir
+ * @arg {String} wantedType - Un string indiquant le type de groupe qu'on veut. Peut être `"simple"`, `"meta"` ou `"all"`. 
+ * @return {String} Le nom de la table dans laquelle la requète doit être effectuée.
+ */
+function getGroupTableName(wantedType){
+    switch(wantedType){
+    case "simple":
+        return "simple_groups";
+    case "SimpleGroup":
+        return "simple_groups";
+    case "meta":
+        return "meta_groups";
+    case "MetaGroup":
+        return "meta_groups";
+    case "all":
+        return "groups";
+    default:
+        throw "invalid type request : " + wantedType + "is not a valid group type";
+    }
+}
+
+/**
+ * @summary Renvoie un unique groupe, ssi ce groupe est visible par l'utilisateur
+ * @desc Pour l'instant, la fonction effectue la même requête que `getAllVisibleGroups` 
+ * et restreint au groupe demandé. Cette fonction peut être implémentée de manière 
+ * plus efficace et plus chiante.
+ * @arg {Object} user - Utilisateur effectuant la requête. 
+ * @arg {String} uid - Identifiant du groupe voulu.
+ * @arg {String} type - Type de groupe voulu. `"simple"`, `"meta"` ou `"all"`.
+ * @return {Promise(group)} Retour de requête knex. Le groupe demandé, si l'utilisateur a le droit de la voire.
+ * @rights user
+ */
+export async function getGroupIfVisible(user, groupUID, type="all"){
+    let group_table_name = getGroupTableName(type);
+    let visible_groups = await selectors.visibleGroups(user);
+    return knex.with('visible_groups', visible_groups).select()
+        .from(group_table_name).innerJoin('visible_groups', function (){
+            this.on('visible_groups.uid', '=', group_table_name + '.uid');
+        }).where(group_table_name + '.uid', groupUID).then(res => res[0]);
+}
+
+export const getSimpleGroupIfVisible = (user, groupUID) => getGroupIfVisible(user, groupUID, "simple");
+export const getMetaGroupIfVisible = (user, groupUID) => getGroupIfVisible(user, groupUID, "meta");
+
+/**
+ * @summary Renvoie tous les groupes simples visibles par l'utilisateur user
+ * @desc Cette fonction effectue une requête knex. 
+ * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. 
+ * @arg {String} wantedType - Type de groupe voulu : `"simple"`, `"meta"` ou `"all"`. 
+ * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire.
+ * @rights user
+ */
+export async function getAllVisibleSimpleGroups (user){
+    let visible_groups = await selectors.visibleGroups(user);
+    return getSimpleGroupsFromCallbacks(user, visible_groups);
+}
+
+/**
+ * @summary Renvoie tous les meta groupes visibles par l'utilisateur user
+ * @desc Cette fonction effectue une requête knex. 
+ * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. 
+ * @arg {String} wantedType - Type de groupe voulu : `"simple"`, `"meta"` ou `"all"`. 
+ * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire.
+ * @rights user
+ */
+export async function getAllVisibleMetaGroups (user){
+    let visible_groups = await selectors.visibleGroups(user);
+    return getMetaGroupsFromCallbacks(user, visible_groups);
+}
+
+/**
+ * @summary Renvoie tous les groupes visibles par l'utilisateur user
+ * @desc Cette fonction effectue une requête knex. Elle gère l'arête de parenté.
+ * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. 
+ * @arg {String} wantedType - Type de groupe voulu : `"simple"`, `"meta"` ou `"all"`. 
+ * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire.
+ * @rights user
+ */
+export async function getAllVisibleGroups(user){
+    let visible_groups = await selectors.visibleGroups(user);
+    return getGroupsFromCallbacks(user, visible_groups);
+}
+
+/**
+ * @summary Teste si un utilisateur est membre d'un groupe
+ * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. 
+ * @arg {Object} groupUID - L'id du groupe dont on veu savoir si l'utilisateur est membre. 
+ * @return {Promise(Boolean)} Boolean indiquant si l'utilisateur est membre du groupe.
+ * @rights user
+ */
+export async function isMember(user, groupUID){
+    let member_list = await getGroupMemberUsers(user, groupUID);
+    return member_list && (member_list.indexOf(groupUID) != -1);
+}
+
+/**
+ * @summary Attribue un UID qui n'a pas encore été utilisé à un groupe
+ * @desc RASifie le string initialUID si necessaire (ramené à de l'ASCCI sans espace), puis si l'uid est deja pris rajoute un n a la fin et reteste
+ * @arg {String} uid - L'uid du groupe dont on veut les administrateurs. 
+ * @return {Promise} Retour de requête knex. Promise qui renvera une liste de tous les utilisateurs ayant droit d'admin sur le groupe
+ * @rights user
+ * remarque : n'importe qui peut tester si un groupe existe en demandant a créer un groupe avec ce nom la et en regardant si
+ * son UID a été modifié. Je ne vois pas comment contourner ce problème, c'est donc une faille permanente de sigma.
+ */
+export function getAvailablegroupUID(initialUID){
+    let rasUID = initialUID.replace(' ', '_').replace(/\W/g, '').toLowerCase();
+    return knex.from('groups').where('uid', rasUID).then(res => {
+        if (res.length == 0) {
+            return (rasUID);
+        } else {
+            return (getAvailablegroupUID(rasUID + 'n'));
+        }
+    });
+}
+
+/**
+ * @summary Créé un groupe si les arguments sont tous valides
+ * @desc Les arguments doivent être valides, sauf pour uid. Une clé uid valide sera générée dans tous les cas. 
+ * Les authorisations de l'utilisateur ne sont pas vérifiées
+ * On teste si l'utilisateur qui envoie la requête a des droits d'admin sur le parent du groupe qui doit être créé, avec la fonction
+ * `getUsersWithAdminRights`.
+ * Si un argument est invalide ou si l'utilisateur n'a pas les droits, la fonction renvoie une erreur
+ * @arg {Object} user - L'utilisateur qui effectue la requête. 
+ * @arg {Object} args - Les arguments envoyés à la mutation. Cf le schéma GraphQL 
+ * @return {Promise} Retour de requête knex. Le groupe qui vient d'être créé. En cas d'echec, renvoie une erreur.
+ * @rights admin (args.parentuid)
+ */
+export async function createSubgroup(user, args){
+    if (typeof args.parentuid != 'string')
+        throw "Illegal argument : parentuid must be a non null string";
+    if (typeof args.name != 'string')
+        throw "Illegal argument : name must be a non null string";
+
+    let rasUID = await getAvailablegroupUID(args.uid);
+
+    // TODO : appeller une fonction de ldap_data pour y créer un groupe.
+    await knex('simple_groups').insert({
+        uid: rasUID,
+        parentuid: args.parentuid,
+        createdAt: knex.fn.now(),
+        updatedAt: this.createdAt,
+        name: args.name,
+        website: args.website,
+        description: args.description,
+        school: args.school,
+        type : "simple"
+    });
+
+    return getGroupIfVisible(user, rasUID);
+}
+
+/**
+ * @summary Créé un groupe si les arguments sont tous valides et l'utilisateur est authorisé
+ * @desc Les arguments doivent être valides, sauf pour uid. Une clé uid valide sera générée dans tous les cas. 
+ * On teste si l'utilisateur qui envoie la requête a des droits d'admin sur le parent du groupe qui doit être créé, avec la fonction `getUsersWithAdminRights`
+ * Si un argument est invalide ou si l'utilisateur n'a pas les droits, la fonction renvoie une erreur
+ * @arg {Object} user - L'utilisateur qui effectue la requête. 
+ * @arg {Object} args - Les arguments envoyés à la mutation. Cf le schéma GraphQL 
+ * @return {Promise} Retour de requête knex. Le groupe qui vient d'être créé. En cas d'echec, renvoie une erreur.
+ * @rights user
+ */
+export async function createGroupIfLegal(user, args){
+    if( await hasAdminRights(user, args.parentuid) ){
+        return createSubgroup(user, args);
+    }else{
+        throw "illegal request : you must have admin rights over a group to create a subgroup of that group";
+    }
+}
+
+/**
+ * @summary Renvoie toues les requêtes de type UserJoinGroup 
+ * @desc Une requête UserJoinGroup est envoyée par un utilisateur à un groupe, 
+ * pour demander à rejoindre ce groupe
+ * @arg {Object} user - L'utilisateur qui effectue la requête. 
+ * @arg {String} args - L'identifiant du groupe qui reçoit la requête. 
+ * @return {Promise(Object)} Retour de requête knex. Toutes les requêtes destinées au groupe.
+ * @rights admin(recipientUID)
+ */
+export async function getUserJoinGroupRequests(user, recipientUID){
+    let result = knex.select('id', 'useruid', 'message').from('user_join_group')
+        .where('recipient', recipientUID);
+    return result.map( obj => {
+        obj.type = "UserJoinGroup";
+        return obj;
+    });
+}
+
+/**
+ * @summary Renvoie toues les requêtes de type GroupJoinEvent 
+ * @desc Une requête UserJoinGroup est envoyée par un groupe à un évènement (donc aux administrateurs de l'évènement), 
+ * pour demander à rejoindre cet évènement.
+ * Remarque : toutes les requêtes ont pour le moment un attribut recipient, 
+ * mais ici il ne sera a terme pas utilisé.
+ * @arg {Object} user - L'utilisateur qui effectue la requête. 
+ * @arg {String} args - L'identifiant du groupe qui reçoit la requête. 
+ * @return {Promise(Object)} Retour de requête knex. Toutes les requêtes destinées au groupe.
+ * @rights speaker(recipientUID)
+ */
+export async function getGroupJoinEventRequests(user, recipientUID){
+    let result = await knex.select('id', 'senderuid', 'eventuid', 'message').from('group_join_event')
+        .where('recipient', recipientUID);
+    return result.map( obj => {
+        obj.type = "GroupJoinEvent";
+        return obj;
+    });
+}
+
+
+/**
+ * @summary Renvoie toues les requêtes de type GroupJoinEvent 
+ * @desc Une requête UserJoinGroup est envoyée par un groupe à un évènement (donc aux administrateurs de l'évènement), 
+ * pour demander à rejoindre cet évènement.
+ * Remarque : toutes les requêtes ont pour le moment un attribut recipient, 
+ * mais ici il ne sera a terme pas utilisé.
+ * @arg {Object} user - L'utilisateur qui effectue la requête. 
+ * @arg {String} args - L'identifiant du groupe qui reçoit la requête. 
+ * @return {Promise(Object)} Retour de requête knex. Toutes les requêtes destinées au groupe.
+ * @rights speaker(recipientUID)
+ */
+export async function getYourGroupHostEventRequests(user, recipientUID){
+    let result = await knex.select('id', 'senderuid', 'eventuid', 'message').from('your_group_host_event')
+        .where('recipient', recipientUID);
+    return result.map( obj => {
+        obj.type = "YourGroupHostEvent";
+        return obj;
+    });
+}
+
+
+//Don't forget the argument user is the guy who makes the request, not the user we want
+export const getUser = (user, userUID) => { 
+    const refactorer = (data) => {
+        console.log("type of nick",typeof data.nickname);
+        if (typeof data.brRoom == 'string') data.brRoom = [data.brRoom];
+
+        return {
+            uid: userUID,
+            lastName: data.sn,
+            givenName: data.givenName,
+            nickname: data.displayName,
+            nationality: data.country,
+            birthdate: data.brBirthdate,
+            groups: data.brMemberOf,
+            mail: data.mail,
+            phone: data.telephoneNumber,
+            address: data.brRoom,
+            promotion: data.brPromo
+        };
+    };
+
+    const result = renseignerSurUtilisateur(user, userUID).then(res => {
+        console.log(res[0]);
+        return refactorer(res[0]);
+    });
+
+    return result;
+};
+
+
+
+/**
+ * @summary Renvoie un message en fonction de son identifiant.
+ * @param {*} user - Utilisateur effectuant la requête.
+ * @param {*} eventID - Identifiant unique de l'événement.
+ * @rights super
+ */
+export async function getMessage(user, messageID){
+    let announcement = await knex.select().from('announcements').where('id', messageID);
+    if(announcement){
+        let res = announcement[0];
+        res.type = "Announcement";
+        return res;
+    }
+    let event = await knex.select().from('events').where('id', messageID);
+    if(event){
+        let res = event[0];
+        res.type = "Event";
+        return res;
+    }
+    return undefined;
+}
+
+/**
+ * @summary Renvoie un message en fonction de son identifiant.
+ * @param {*} user - Utilisateur effectuant la requête.
+ * @param {*} eventID - Identifiant unique de l'événement.
+ * @rights super
+ */
+export async function getMessageIfVisible(user, messageID){
+    let announcement = await knex
+        .with('visible_announcements', await selectors.visibleAnnouncements(user))
+        .select().from('visible_announcements').where('id', messageID);
+    if(announcement){
+        let res = announcement[0];
+        res.type = "Announcement";
+        return res;
+    }
+    let event = await knex
+        .with('visible_events', await selectors.visibleEvents(user))
+        .select().from('visible_events').where('id', messageID);
+    if(event){
+        let res = event[0];
+        res.type = "Event";
+        return res;
+    }
+    return undefined;
+}
+
+
+
+export async function getMessageHosts(user, messageID){
+
+}
+
+/**
+ * @summary Renvoie simplement un groupe en fonction de son identifiant.
+ * @param {Object} user - Utilisateur effectuant la requête.
+ * @param {String} groupUID - Identifiant unique du groupe.
+ * @author manifold 
+ * @rights super
+ */
+export const getGroup = (user, groupUID) => {
+    // Une sélection sur une table renvoie un tableau.
+    // Knex renvoie une promesse, qui se résout en le tableau sélectionné.
+    // On récupère son unique valeur, puisqu'on filtre sur l'identifiant unique.
+    return knex.select().from('groups').where('uid',groupUID).then(results => results [0]);
+};
+
+/**
+ * @summary Renvoie simplement un groupe simple en fonction de son identifiant.
+ * @param {Object} user - Utilisateur effectuant la requête.
+ * @param {String} groupUID - Identifiant unique du groupe.
+ * @author manifold 
+ * @rights super
+ */
+export const getSimpleGroup = (user, groupUID) => {
+    return knex.select().from('simple_groups').where('uid',groupUID).then(results => results [0]);
+};
+
+/**
+ * @summary Renvoie simplement un meta groupe en fonction de son identifiant.
+ * @param {Object} user - Utilisateur effectuant la requête.
+ * @param {String} groupUID - Identifiant unique du groupe.
+ * @author manifold 
+ * @rights super
+ */
+export const getMetaGroup = (user, groupUID) => {
+    return knex.select().from('meta_groups').where('uid',groupUID).then(results => results [0]);
+};
+
+export async function getEvent(user, eventID){
+    console.log(eventID);
+    let event_list = await knex('events').select().where('id', eventID);
+    console.log(event_list);
+    return event_list[0];
+}
+
+/**
+ * @summary Refuse une requête d'un groupe voulant rejoindre un évènement
+ * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. 
+ * @arg {Int} requestID - L'id de la requête à refuser. 
+ * @return {Promise(Boolean)} Vrai si l'opération a réussie;
+ * @rights admin(request.recipient)
+ */
+export async function denyGroupJoinEventRequest(user, requestID){
+    await knex('group_join_event').where('id', requestID).del();
+    return true;
+}
+
+/**
+ * @summary Refuse une requête d'un groupe voulant rejoindre un évènement
+ * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. 
+ * @arg {Int} requestID - L'id de la requête à refuser. 
+ * @return {Promise(Boolean)} Vrai si l'opération a réussie;
+ * @rights admin(request.recipient)
+ */
+export async function acceptGroupJoinEventRequest(user, requestID){
+    let request = await knex('group_join_event').select().where('id', requestID);
+    if( !request)
+        return false;
+    await knex('group_join_event').where('id', requestID).del();
+    let group = request[0].senderuid;
+    let event = request[0].eventuid;
+    await knex('group_participation').insert({
+        group : group,
+        message : event,
+        status : "join"
+    });
+    return;
+
+}
+
+
+/**
+ * @summary Refuse une requête d'un groupe voulant rejoindre un évènement
+ * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. 
+ * @arg {Int} requestID - L'id de la requête à refuser. 
+ * @return {Promise(Boolean)} Vrai si l'opération a réussie;
+ * @rights admin(request.recipient)
+ */
+export async function denyYourGroupHostEventRequest(user, requestID){
+    await knex('your_group_host_event').where('id', requestID).del();
+    return true;
+}
+
+/**
+ * @summary Refuse une requête d'un groupe voulant rejoindre un évènement
+ * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. 
+ * @arg {Int} requestID - L'id de la requête à refuser. 
+ * @return {Promise(Boolean)} Vrai si l'opération a réussie;
+ * @rights admin(request.recipient)
+ */
+export async function acceptYourGroupHostEventRequest(user, requestID){
+    let request = await knex('your_group_host_event').select().where('id', requestID);
+    if( !request)
+        return false;
+    await knex('group_join_event').where('id', requestID).del();
+    let group = request[0].recipient;
+    let event = request[0].eventuid;
+    await knex('group_message_relationships').insert({
+        group : group,
+        message : event,
+        status : "host"
+    });
+    return;
+
+}
+
+export function takeAdminRights(user, groupUID, justification){
+    return knex('taken_rights').insert({
+        user_uid : user.uid,
+        group_uid : groupUID,
+        justification : justification
+    });
+}
+
+/**
+ * @summary Renvoie les membres d'un groupe quelquonque.
+ * @param {Object} user - Utilisateur effectuant la requête.
+ * @param {String} metaGroupUID - Identifiant unique du groupe.
+ * @return {Promise(List)} Une liste des uid de tous les membres du groupe
+ * @author akka vodol 
+ * @rights member(metaGroupUID)
+ */
+export async function getGroupMemberUsers(user, GroupUID){
+    let type = await list_selectors.getGroupType(user, GroupUID);
+    switch( type ){
+    case "SimpleGroup":
+        //return listerMembres(user, GroupUID);
+        return ["anatole.romon"];
+    case "MetaGroup":
+        return getMetaGroupMemberUsers(user, GroupUID);
+    default:
+        return undefined;
+    }
+}
+/**
+ * @summary Renvoie les membres d'un meta groupe.
+ * @param {Object} user - Utilisateur effectuant la requête.
+ * @param {String} metaGroupUID - Identifiant unique du groupe.
+ * @return {Promise(List)} Une liste des uid de tous les membres du groupe
+ * @author akka vodol 
+ * @rights member(metaGroupUID)
+ */
+export async function getMetaGroupMemberUsers(user, metaGroupUID){
+    let member_group_list = await selectors.metaGroupMembers(user, metaGroupUID).then(cb => cb(knex));
+    let members = [];
+    for(let memberGroup of await member_group_list){
+        members = members.concat(getGroupMemberUsers(user, metaGroupUID));
+    }
+}
+
+export async function getSimpleGroupsFromCallbacks (user, selection){
+    return knex.with('selection', selection).select().from("simple_groups")
+        .innerJoin('selection', function (){
+            this.on('selection.uid', '=', 'simple_groups.uid');
+        });
+}
+
+export async function getMetaGroupsFromCallbacks (user, selection){
+    return knex.with('selection', selection).select().from("meta_groups")
+        .innerJoin('selection', function (){
+            this.on('selection.uid', '=', 'meta_groups.uid');
+        });
+}
+
+/**
+ * @summary Renvoie tous les groupes dans l'intersection définie par les callbacks
+ * @desc Cette fonction effectue une requête knex. Elle gère l'arête de parenté.
+ * @arg {Object} user - Représente l'utilisateur qui a effectué la requête. 
+ * @arg {String} wantedType - Type de groupe voulu : `"simple"`, `"meta"` ou `"all"`. 
+ * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire.
+ * @rights user
+ */
+export async function getGroupsFromCallbacks(user, cbList){
+    let all_simple_groups = await getSimpleGroupsFromCallbacks(user, cbList);
+    let all_meta_groups = await getMetaGroupsFromCallbacks(user, cbList);
+    return all_simple_groups.concat(all_meta_groups);
+}
+
+/*
+ * réflexion sur une façon possible de gérer les utilisateurs sans en demander trop à LDAP
+ * Sans utilité pour le moment, ne faites pas attention 
+ */
+function smartUserObject(user, uid){
+    this.user = user;
+    this.uid = uid;
+
+    this.resolution = {};
+    let resolutionAlias = this.resolution;
+
+    let attributeDictionnary = {
+        givenName : "givenName"
+    };
+
+    for(let attribute in attributeDictionnary){
+        this[attribute] = function(){
+            return new Promise((resolve, reject) => {
+                resolutionAlias[attributeDictionnary[attribute]] = resolve;
+            });
+        };
+    }
+
+    this.resolve = async function(){
+        let userObject = await renseignerSurUtilisateur(this.user, this.uid);
+        for(let attribute in this.resolution){
+            this.resolution[attribute](userObject.attribute);
+        }
+    };
+}
\ No newline at end of file
diff --git a/src/graphql/connectors/list_selectors.js b/src/graphql/connectors/list_selectors.js
new file mode 100644
index 0000000000000000000000000000000000000000..831c8ce76a894751f39cc2cd28a1b06cf6a3efd7
--- /dev/null
+++ b/src/graphql/connectors/list_selectors.js
@@ -0,0 +1,90 @@
+import knex from '../../../db/knex_router';
+import { renseignerSurUtilisateur, repliquerTOLdesIds, 
+    listerGroupes, listerMembres, listerAdministrateurs 
+} from '../../ldap/ldap_data';
+import * as selectors from './selectors';
+
+/**
+ * @summary Renvoie le type d'un groupe.
+ * @function
+ * @desc Parcours les BDD pour savoir dans laquelle se trouve le groupe ayant l'UID donné. 
+ * Cette opération nécéssite un parcours de base de donnée, et il est préférable de ne pas 
+ * sans servir si on a un autre moyend de connaitre le typed d'un groupe
+ * (Par exemple, si on dispose d'un retour de BDD pour ce groupe. Le champ 'type' indique alors son type.)
+ * @arg {Object} user - Objet contenant un attribut `uid` de type `string`. 
+ * User représente l'utilisateur qui a effectué la requête. 
+ * @arg {Object} groupUID - L'id du groupe dont on veut connaître le type.
+ * @return {Promise(String)} Un string représentant le type du groupe.
+ * Peut être "SimpleGroup" ou "MetaGroup". Renvoie `Undefined` si le groupe n'existe pas
+ * @rights super
+ */
+export const getGroupType = (user, groupUID) => {
+    return knex('simple_groups').select('uid').where('uid', groupUID).then( sg_res => {
+        if(sg_res)
+            return "SimpleGroup";
+        return knex('meta_groups').select('uid').where('uid', groupUID).then(mg_res => {
+            if(mg_res)
+                return "MetaGroup";
+            return undefined;
+        });
+    });
+};
+
+/**
+ * @summary renvoie tous les groupes sur lesquels un utilisateur a des droits de supervision
+ * @desc Cette fonction effectue des requêtes knex. Elle parcoure recursivement l'arbre de parenté,
+ * Et cela aurait été trop lourd de la faire renvoyer un callback définissant une requête.
+ * @arg {Object} user - Objet contenant un attribut `uid` de type `string`. 
+ * User représente l'utilisateur qui a effectué la requête. 
+ * @return {Promise(array)} Une liste des uid de tous les groupes que user supervise.
+ * @rights user
+ */
+export async function supervisedGroups(user){
+    function difference(arr1, arr2){
+        return arr1.filter( e => (arr2.indexOf(e) < 0));
+    }
+    async function recursive_explorer(visited_groups, start_groups){
+        let child_simple_groups = await knex.select('uid').distinct().from('simple_groups')
+            .whereIn('parentuid', start_groups);
+        let child_meta_groups = await knex.select('union_uid').as('uid').distinct()
+            .from('meta_group_membership').where('status', 'admin')
+            .whereIn('member_uid', child_simple_groups);
+        let new_start_groups = difference(child_simple_groups.concat(child_meta_groups), visited_groups);
+        let new_visited_groups = visited_groups.concat(new_start_groups);
+        if(new_start_groups)
+            return recursive_explorer(new_visited_groups, new_start_groups);
+        else
+            return new_visited_groups;
+        
+    }
+    let groups_with_admin = await selectors.groupsWithAdmin(user)(knex);
+    return recursive_explorer([], groups_with_admin);
+}
+
+/**
+ * @summary Renvoie tous les utilisateurs ayant des droits d'administrateur sur un groupe.
+ * @function
+ * @desc Les utilisateurs qui ont un droit d'administrateur sur un groupe simple sont ses administrateurs 
+ * et les utilisateurs ayant droit d'admin sur son parent.
+ * Les utilisateurs ayant droit d'admin sur un meta-groupe sont les utilisateurs 
+ * ayant droit d'admin sur un des groupes membres
+ * @arg {String} uid - L'uid du groupe dont on veut les administrateurs. 
+ * @return {Promise} Retour de requête knex. Promise qui renvera une liste 
+ * de tous les utilisateurs ayant droit d'admin sur le groupe
+ * rights member(groupUID)
+ */
+export async function usersWithAdminRights(user, groupUID){
+    let group_type = await getGroupType(user, groupUID);
+    if(group_type == "SimpleGroup"){
+        let added_admins = await knex.select('user_uid').from('taken_rights').where('group_uid', groupUID);
+        let admin_list = ["wilson.jallet", "louis.vanneau"]; // await listerAdministrateurs(user, groupUID);
+        return admin_list.concat( added_admins.map( o => o.user_uid) );
+    }else{
+        let mg_members = await selectors.metaGroupAdminMembers(user, groupUID)(knex);
+        let admin_users = [];
+        while(mg_members){
+            admin_users = admin_users.concat(await usersWithAdminRights(mg_members.pop()));
+        }
+        return admin_users;
+    }
+}
diff --git a/src/graphql/connectors/selectors.js b/src/graphql/connectors/selectors.js
new file mode 100644
index 0000000000000000000000000000000000000000..ca9124bc82f6dc646fcab7e60a967d5d5454b3a8
--- /dev/null
+++ b/src/graphql/connectors/selectors.js
@@ -0,0 +1,132 @@
+/**
+ * @file Des callbacks qui sélectionnent un sous-ensemble de groupes.
+ * @author akka vodol
+ */
+
+import { renseignerSurUtilisateur, repliquerTOLdesIds, 
+    listerGroupes, listerMembres, listerAdministrateurs 
+} from '../../ldap/ldap_data';
+
+//Give a user, get the groups linked to that user
+
+/**
+ * @summary 2Renvoie une liste des id de tous les groupes visibles par l'utilisateur
+ * @desc Cette fonction génère un callback qui créé une table contenant les uid de tous les groupes visibles
+ * @arg {Object} user - Objet contenant un attribut `uid` de type `string`. 
+ * User représente l'utilisateur qui a effectué la requête. 
+ * @return {Promise(Callback)} callback contruisant une requête knex pour une table de tous les id visibles.
+ * @rights user
+ */
+export function  visibleGroups(user){
+    return async function (global_query_builder){
+        //let group_ids = await listerGroupes(user, user.uid);
+        let group_ids = ["br, kes, faerix"];
+        console.log("we got this far");
+        if (typeof group_ids == "undefined")
+            throw "invalid user";
+        var membered_groups = qb => qb.select('simple_groups.uid').from('simple_groups').whereIn('uid', group_ids.concat(['kes']));
+        var directly_visible_simple_groups = qb =>  qb.with('membered_groups', membered_groups)
+            .select('simple_groups.uid').from('simple_groups').distinct()
+            .innerJoin('membered_groups',
+                function () {
+                    this.on('simple_groups.uid', '=', 'membered_groups.uid')
+                        .orOn('simple_groups.parentuid', '=', 'membered_groups.uid');
+                }
+            );
+        return directly_visible_simple_groups(global_query_builder);
+    };
+}
+
+export async function groupsWithSpeaker(user){
+    return function (query_builder){
+        return groupsWithAdmin(user);
+    };
+}
+
+export async function groupsWithAdmin(user){
+    return function (query_builder){
+        return null;
+    };
+}
+
+
+// Give a user, get the messages linked to that user
+
+export async function visibleAnnouncements(user){
+    return query_builder => {
+        return query_builder;
+    };
+}
+
+export async function visibleEvents(user){
+    return query_builder => {
+        return query_builder;
+    };
+}
+
+export async function messageHosts(user, messageID){
+    return function(query_builder){
+        return query_builder.select('group').as('uid').from('group_message_relationships')
+            .where('message', messageID);
+    };
+}
+
+//Give a group, get the users linked to that group
+
+/**
+ * @summary Renvoie un callback qui génère tous les membres d'un meta-groupe.
+ * @param {Object} user - Utilisateur effectuant la requête.
+ * @param {String} metaGroupUID - Identifiant unique du groupe.
+ * @return {Promise(callback(groups))} a callback to build a query for the members of a group
+ * It doesn't need to be a promise, but I figure having all of my functions return promises is 
+ * easier than keeping track of which functions do and do not return promises.
+ * @author akka vodol 
+ * @rights member(metaGroupUID)
+ */
+export async function metaGroupMembers(user, metaGroupUID){
+    return function(query_builder){
+        return query_builder.distinct().select().from('groups')
+            .innerJoin('meta_group_membership', 'groups.uid', 'meta_group_membership.member_uid')
+            .where('meta_group_membership.union_uid', '=', metaGroupUID);
+    };
+}
+
+/**
+ * @summary Renvoie un callback qui génère tous les membres admin d'un meta-groupe.
+ * @param {Object} user - Utilisateur effectuant la requête.
+ * @param {String} metaGroupUID - Identifiant unique du groupe.
+ * @return {Promise(callback)} a callback to build a query for the admin members of a group
+ * @author akka vodol 
+ * @rights member(metaGroupUID)
+ */
+export async function metaGroupAdminMembers(user, metaGroupUID){
+    return function(query_builder){
+        return query_builder.distinct().select().from('groups')
+            .innerJoin('meta_group_membership', 'groups.uid', 'meta_group_membership.member_uid')
+            .where('meta_group_membership.union_uid', '=', metaGroupUID)
+            .where('meta_group_membership.status', '=', 'admin');
+    };
+}
+
+export async function callbackIntersection(callbackList){
+    return function(query_builder){
+        let cb = callbackList.pop();
+        if(callbackList){
+            let intersection = callbackIntersection(callbackList);
+            return function(query_builder){
+                return query_builder.with('callback_set', cb)
+                    .with('intersection', intersection)
+                    .select('intersection.uid').from('intersection')
+                    .innerJoin('callback_set', function(){
+                        this.on('callback_set.uid', '=', 'intersection.uid');
+                    });
+            };
+        }else{
+            return cb;
+        }
+    };
+}
+
+export async function callbackUnion(callbackList){
+    return null;
+}
\ No newline at end of file
diff --git a/src/graphql/db_utils.js b/src/graphql/db_utils.js
deleted file mode 100644
index f9330dc1b8caf03ab84702effd9a207cbc4fb836..0000000000000000000000000000000000000000
--- a/src/graphql/db_utils.js
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
- * @file Fonctions pour interagir avec la BDD sigma et le LDAP.
- * @author akka vodol
- */
-import knex from '../../db/knex_router';
-import { renseignerSurUtilisateur, repliquerTOLdesIds, listerGroupes, listerMembres, listerAdministrateurs } from '../ldap/ldap_data';
-import { exportAllDeclaration } from 'babel-types';
-
-export { renseignerSurUtilisateur, repliquerTOLdesIds, listerMembres };
-
-/**
- * @summary Renvoie tous les utilisateurs ayant des droits d'administrateur sur un groupe.
- * @function
- * @desc Les utilisateurs qui ont un droit d'administrateur sur un groupe sont ses administrateurs et les utilisateurs ayant droit d'admin sur son parent
- * @arg {String} uid - L'uid du groupe dont on veut les administrateurs. 
- * @return {Promise} Retour de requête knex. Promise qui renvera une liste de tous les utilisateurs ayant droit d'admin sur le groupe
- */
-export const getUsersWithAdminRights = (user, groupUID) => {
-    return listerAdministrateurs(user, groupUID).then(adminList => {
-        if (typeof adminList == "undefined")
-            return undefined;
-        else
-            return knex('groups').select('parentuid').where('uid', groupUID).then(req => {
-                if (req[0].parentuid)
-                    return getUsersWithAdminRights(user, req[0].parentuid).then(parentAdmins => {
-                        return adminList.concat(parentAdmins);
-                    });
-                else
-                    return adminList.concat(['anatole.romon']); // pour les besoins des tests, anatole romon a tout les droits
-            });
-    });
-};
-
-/**
- * @summary teste si un utilisateur a des droits
- * @desc Cette fonction effectue une requête knex. Elle gère l'arête de parenté.
- * @arg {Object} user - Objet contenant un attribut *uid* de type *string*. User représente l'utilisateur qui a effectué la requête. 
- * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire.
- */
-export const hasAdminRights = (user, groupUID) => {
-    return getUsersWithAdminRights(user, groupUID).then(adminList => {
-        return (typeof adminList != "undefined" && adminList.indexOf(user.uid) != -1);
-    });
-};
-
-/**
- * @summary Renvoie tous les groupes visibles par l'utilisateur user
- * @desc Cette fonction effectue une requête knex. Elle gère l'arête de parenté.
- * @arg {Object} user - Objet contenant un attribut *uid* de type *string*. User représente l'utilisateur qui a effectué la requête. 
- * @return {Promise} Retour de requête knex. Liste de tous les groupes que l'utilisateur a le droit de voire.
- */
-export const getAllVisibleGroups = (user) => {
-
-    return listerGroupes(user, user.uid).then(group_ids => {
-        if (typeof group_ids == "undefined")
-            throw "invalid user";
-        var membered_groups = qb => qb.select().from('groups').whereIn('uid', group_ids.concat(['kes']));
-        /* membered_groups est un callback qui reçoit un argument qb représentant un objet de requête (un truc qui s'utilise comme knex())
-        *  et effectue dessus la requête pour obtenir une table de tous les groupes dont user est membre
-        *  with est ensuite utilisé pour donner à ce retour de requête l'alias 'membered_groups'.
-        *  Cette table peut ainsi être JOIN avec la table groups. La condition de Join est donnée selon une syntaxe recopiée depuis la Doc Knex
-        *  On récupère tous les groupes tels que le groupe est dans membered_groups ou le parent est dans membered_groups
-        */
-        return knex.with('membered_groups', membered_groups).distinct('groups.*').select().from('groups').innerJoin('membered_groups',
-            function () {
-                this.on('groups.uid', '=', 'membered_groups.uid').orOn('groups.parentuid', '=', 'membered_groups.uid');
-            }
-        );
-    });
-};
-
-
-/**
- * @summary Teste si un utilisateur est membre d'un groupe
- * @arg {Object} user - Objet contenant un attribut *uid* de type *string*. User représente l'utilisateur qui a effectué la requête. 
- * @arg {Object} groupUID - L'id du groupe dont on veu savoir si l'utilisateur est membre. 
- * @return {Promise(Boolean)} Boolean indiquant si l'utilisateur est membre du groupe.
- */
-export const isMember = (user, groupUID) => {
-    return listerGroupes(user, user.uid).then(group_ids => group_ids && group_ids.indexOf(groupUID) != -1);
-};
-
-/**
- * @summary Renvoie un unique groupe, ssi ce groupe est visible par l'utilisateur
- * @desc Actuellement, la fonction effectue la même requête que *getAllVisibleGroups* et restreint au groupe demandé. Cette fonction peut être implémentée de manière plus efficace et plus chiante.
- * @arg {Object} user - Objet contenant un attribut *uid* de type *string*. User représente l'utilisateur qui a effectué la requête. 
- * @arg {String} uid - uid du groupe que l'on veut voire. 
- * @return {Promise(group)} Retour de requête knex. Le groupe demandé, si l'utilisateur a le droit de la voire.
- */
-export const getGroupIfVisible = (user, groupUID) => {
-    return listerGroupes(user, user.uid).then(group_ids => {
-        if (typeof group_ids == "undefined")
-            throw "invalid user";
-        var membered_groups = qb => qb.select().from('groups').whereIn('uid', group_ids.concat(['kes']));
-        return knex.with('membered_groups', membered_groups).distinct('groups.*').select().from('groups').innerJoin('membered_groups',
-            function () {
-                this.on('groups.uid', '=', 'membered_groups.uid').orOn('groups.parentuid', '=', 'membered_groups.uid');
-            }
-        ).where('groups.uid', groupUID).then(res => {
-            return res[0];
-        });
-    });
-};
-
-/**
- * @summary Attribue un UID qui n'a pas encore été utilisé à un groupe
- * @desc RASifie le string initialUID si necessaire (ramené à de l'ASCCI sans espace), puis si l'uid est deja pris rajoute un n a la fin et reteste
- * @arg {String} uid - L'uid du groupe dont on veut les administrateurs. 
- * @return {Promise} Retour de requête knex. Promise qui renvera une liste de tous les utilisateurs ayant droit d'admin sur le groupe
- */
-export const getAvailablegroupUID = (initialUID) => {
-    let rasUID = initialUID.replace(' ', '_').replace(/\W/g, '').toLowerCase();
-    return knex.from('groups').where('uid', rasUID).then(res => {
-        if (res.length == 0) {
-            return (rasUID);
-        } else {
-            return (getAvailablegroupUID(rasUID + 'n'));
-        }
-    });
-};
-
-/**
- * @summary Créé un groupe si les arguments sont tous valides
- * @desc Les arguments doivent être valides, sauf pour uid. Une clé uid valide sera générée dans tous les cas. 
- * Les authorisations de l'utilisateur ne sont pas vérifiées
- * On teste si l'utilisateur qui envoie la requête a des droits d'admin sur le parent du groupe qui doit être créé, avec la fonction *getUsersWithAdminRights*
- * Si un argument est invalide ou si l'utilisateur n'a pas les droits, la fonction renvoie une erreur
- * @arg {Object} user - L'utilisateur qui effectue la requête. 
- * @arg {Object} args - Les arguments envoyés à la mutation. Cf le schéma GraphQL 
- * @return {Promise} Retour de requête knex. Le groupe qui vient d'être créé. En cas d'echec, renvoie une erreur.
- */
-export const createSubgroup = (user, args) => {
-    if (typeof args.parentuid != 'string')
-        throw "Illegal argument : parentuid must be a non null string";
-    if (typeof args.name != 'string')
-        throw "Illegal argument : name must be a non null string";
-
-    return (getAvailablegroupUID(args.uid).then(rasUID => {
-        // TODO : appeller une fonction de ldap_data pour y créer un groupe.
-        return knex('groups').insert({
-            uid: rasUID,
-            parentuid: args.parentuid,
-            createdAt: knex.fn.now(),
-            updatedAt: this.createdAt,
-            name: args.name,
-            website: args.website,
-            description: args.description,
-            school: args.school
-        }).then(res => {
-            return getGroupIfVisible(user, rasUID);
-        });
-    }));
-};
-
-/**
- * @summary Créé un groupe si les arguments sont tous valides et l'utilisateur est authorisé
- * @desc Les arguments doivent être valides, sauf pour uid. Une clé uid valide sera générée dans tous les cas. 
- * On teste si l'utilisateur qui envoie la requête a des droits d'admin sur le parent du groupe qui doit être créé, avec la fonction *getUsersWithAdminRights*
- * Si un argument est invalide ou si l'utilisateur n'a pas les droits, la fonction renvoie une erreur
- * @arg {Object} user - L'utilisateur qui effectue la requête. 
- * @arg {Object} args - Les arguments envoyés à la mutation. Cf le schéma GraphQL 
- * @return {Promise} Retour de requête knex. Le groupe qui vient d'être créé. En cas d'echec, renvoie une erreur.
- */
-export const createGroupIfLegal = (user, args) => {
-    return hasAdminRights(user, args.parentuid).then(answer => {
-        if (!answer)
-            throw "illegal request : you must have admin rights over a group to create a subgroup of that group";
-        return createSubgroup(user, args);
-    });
-};
-
-export const getUserJoinGroupRequests = (user, recipientUID) => {
-    return knex('user_join_group').select(/*'id', 'useruid', 'message'*/)/*.where('recipient', recipientUID)*/;
-};
-
-//Don't forget the argument user is the guy who makes the request, not the user we want
-export const getUser = (user, userUID) => { 
-    return new Promise( (resolve, reject) => {
-        resolve({
-            givenName : "Jean-Michel",
-            lastName : "Samarchepas",
-            uid : "jm",
-            birthdate : "dans le turfu",
-            mail : "email.email@email.com",
-            phone : "06 60 06 60 06",
-            groups : [],
-            likes : [],
-            address : "aussi dans le turfu"
-        });
-    });
-    /*return renseignerSurUtilisateur(user, userUID).then(res => {
-        return {
-            givenName : res[0].givenName,
-            lastName : res[0].lastName,
-            uid : userUID,
-            birthdate : res[0].brBirthdate,
-            mail : res[0].mail,
-            phone : res[0].telephoneNumber,
-            groups : [],
-            likes : [],
-            address : res[0].brRoom
-        };
-    });*/
-};
-
-export const getEvent = (user, eventID) => {
-    return null;
-};
-
-export const getGroup = (user, groupUID) => {
-    return null;
-};
\ No newline at end of file
diff --git a/src/graphql/resolvers.js b/src/graphql/resolvers.js
new file mode 100644
index 0000000000000000000000000000000000000000..36e8fbc496f2369f24b6db57215fd15400d317e2
--- /dev/null
+++ b/src/graphql/resolvers.js
@@ -0,0 +1,352 @@
+/**
+ * @file Implémentation des requêtes GraphQL.
+ * @author akka vodol
+*/
+import { request } from 'https';
+import _ from 'lodash';
+import { assertBinaryExpression } from 'babel-types';
+import knex from '../../db/knex_router';
+
+import * as connectors from './connectors/connectors.js';
+import { connect } from 'http2';
+
+/** 
+ * @description Résolveurs des différentes requêtes GraphQL
+*/
+export const resolvers = {
+    // @rights user
+    Query: {
+
+        asAdmin: async function (obj, args, context){
+            if(await connectors.hasAdminRights(context.user, args.groupUID))
+                return {groupUID : args.groupUID};
+            else
+                throw "You do not have admin rights over this group";
+        },
+
+        asMember: async function (obj, args, context){
+            let res = await connectors.isMember(context.user, args.groupUID);
+            console.log(res);
+            if(res/*await connectors.isMember(context.user, args.groupUID) || connectors.hasAdminRights(context.user, args.groupUID)*/){
+                return {groupUID : args.groupUID};
+            }else
+                throw "You do not have member rights over this group";
+        },
+
+        accessGroups: (obj, args, context) => {
+            return {};
+        },
+
+        accessPosts: (obj, args, context) => {
+            return {};
+        },
+
+        accessUsers: (obj, args, context) => {
+            return {};
+        },
+    },
+
+    // @rights user
+    GroupQuery : {
+        allGroups: (obj, args, context) => {
+            return connectors.getAllVisibleGroups(context.user);
+        },
+        allSimpleGroups: (obj, args, context) => {
+            return connectors.getAllVisibleSimpleGroups(context.user);
+        },
+
+        group: (obj, args, context) => {
+            return connectors.getGroupIfVisible(context.user, args.uid);
+        },
+        simpleGroup: (obj, args, context) => {
+            return connectors.getSimpleGroupIfVisible(context.user, args.uid);
+        },
+        metaGroup: (obj, args, context) => {
+            return connectors.getMetaGroupIfVisible(context.user, args.uid);
+        }
+    },
+
+    // @rights use
+    MessageQuery : {
+        allPosts: (obj, args, context) => {
+            return knex.select().from('posts');
+        },
+        message: (obj, args, context) => {
+            const result = knex.select().from('messages').where('id','=',args.id);
+            return result.then((res) => res[0]);
+        },
+    },
+
+    // @rights user
+    UserQuery: {
+        user: (obj, args, context) => {
+            
+            return connectors.getUser(context.user,args.uid);
+        },
+
+        searchTOL: (obj, args, context) => {
+            console.log(args);
+            return connectors.repliquerTOLdesIds(context.user, {
+                givenName: args.givenName,
+                lastName: args.lastName,
+                nickname: args.nickname,
+                nationality: args.nationality,
+                school: args.school,
+                promotion: args.promotion,
+                groups: args.groups,
+                studies: args.studies,
+                sport: args.sport,
+                phone: args.phone,
+                mail: args.mail,
+                adress: args.adress,
+                ip: args.ip
+            });
+        }
+    },
+
+    // @rights admin(obj.groupUID)
+    AdminQuery: {
+        isAdmin: (obj, args, context) => {
+            return true;
+        },
+
+        allRequests: async function(obj, args, context){
+            let ujg_requests = await connectors.getUserJoinGroupRequests(context.user, obj.groupUID);
+            let gje_requests = await connectors.getGroupJoinEventRequests(context.user, obj.groupUID);
+            let yghe_requests = await connectors.getYourGroupHostEventRequests(context.user, obj.groupUID);
+            return ujg_requests.concat(gje_requests).concat(yghe_requests);
+        }
+    },
+
+    // @rights member(obj.groupUID)
+    MemberQuery: {
+        isMember: (obj, args, context) => {
+            return true;
+        },
+
+        allMembers: async function (obj, args, context){
+            let cb = await connectors.getMetaGroupMemberUsers(context.user, obj.groupUID);
+            return cb(knex);
+        }
+    },
+
+    SpeakerQuery: {
+
+        allRequests: async function(obj, args, context){
+            let gje_requests = await connectors.getGroupJoinEventRequests(context.user, obj.groupUID);
+            let yghe_requests = await connectors.getYourGroupHostEventRequests(context.user, obj.groupUID);
+            return gje_requests.concat(yghe_requests);
+        }
+    },
+
+    Request : {
+        __resolveType : function(obj){
+            return obj.type;
+        }
+    },
+
+    // @rights admin(obj.groupUID)
+    UserJoinGroup: {
+        user : (obj, args, context) => {
+            return connectors.getUser(context.user, obj.useruid);
+            /*return connectors.getUser(context.user, "quentin.gendre");
+            if(obj.useruid === "anatole.romon"){
+                return connectors.getUser(context.user, "anatole.romon").then(res => {
+                    return connectors.getUser(context.user, "quentin.gendre");
+                });
+            }else{
+                return new Promise( (resolve, reject) => {
+                    resolve({givenName : "patrick"});
+                });
+            }*/
+        }
+    },
+
+    // @rights speaker(obj.groupUID)
+    GroupJoinEvent : {
+        event: (obj, args, context) => {
+            return connectors.getEvent(context.user, obj.eventuid);
+        },
+        groupWantingToJoin: (obj, args, context) => {
+            return connectors.getGroup(context.user, obj.senderuid);
+        }
+    },
+
+    // @rights speaker(obj.groupUID)
+    YourGroupHostEvent : {
+        event: (obj, args, context) => {
+            return connectors.getEvent(context.user, obj.eventuid);
+        },
+        sender: (obj, args, context) => {
+            return connectors.getGroup(context.user, obj.senderuid);
+        }
+    },
+
+    // @rights user
+    User : {
+        groups : (obj, args, context) => {
+            let result = Promise.all(obj.groups.map((grid) => {
+                return connectors.getSimpleGroup(context.user,grid);
+            }));
+
+            return result.then(groups => {
+                return _.filter(groups,(o) => !_.isUndefined(o));
+            });
+        },
+
+    },
+
+    // @rights user
+    Mutation: {
+
+        asSuperviser : function (obj, args, context){
+            return {groupUID : args.groupUID, justification : "kes"};
+        },
+
+        asAdmin: (obj, args, context) => {
+            return connectors.hasAdminRights(context.user, args.groupUID).then(res => {
+                if(res)
+                    return {groupUID : args.groupUID};
+                else
+                    throw "You do not have admin rights over this group";
+            });
+        },
+
+        asSpeaker: (obj, args, context) => {
+            return connectors.hasAdminRights(context.user, args.groupUID).then(res => {
+                if(res)
+                    return {groupUID : args.groupUID};
+                else
+                    throw "You do not have publishing rights in this group";
+            });
+        },
+
+        asMember: (obj, args, context) => {
+            return connectors.isMember(context.user, args.groupUID).then(res => {
+                if(res)
+                    return {groupUID : args.groupUID};
+                else
+                    throw "You are  not a member of this group";
+            });
+        },
+        asViewer: (obj, args, context) => {
+            return connectors.getGroupIfVisible(context.user, args.groupUID).then(res => {
+                if(res)
+                    return {groupUID : args.groupUID};
+                else
+                    throw "You are  not a member of this group";
+            });
+        }
+    },
+
+    // @rights : superviser(obj.groupUID)
+    SuperviserMutation: {
+
+        runAdminOperation : function (obj, args, context){
+            return obj;
+        },
+
+        takeAdminRights : async function(obj, args, context){
+            console.log(obj);
+            await connectors.takeAdminRights(context.user, obj.groupUID, obj.justification);
+            return connectors.getGroup(context.user, obj.groupUID);
+        }
+    },
+
+    // @rights admin(obj.groupUID)
+    AdminMutation: {
+        isAdmin: (obj, args, context) => {
+            return true;
+        
+        },
+        createSubgroup: (obj, args, context) => {
+            args.parentuid = obj.groupUID;
+            return connectors.createSubgroup(context.user, args);
+        },
+
+        editGroup: (obj, args, context) => {
+            return null;
+        }
+    },
+
+    // @rights viewer(obj.groupUID)
+    ViewerMutation: {
+        requestJoin: (obj, args, context) => {
+            console.log(obj);
+            return null;
+        }
+    },
+
+    Post: {
+        authors: (obj, args, context) => {
+            return knex.select().from('groups').whereIn('uid',obj.authors);
+        }
+    },
+
+    Message: {
+
+        __resolveType: function(obj){
+            return obj.type;
+        }
+
+    },
+
+    Announcement: {
+        forEvent : function(obj, args, context){
+            // le champ is_announcement n'existe que sur les Events
+            // une ligne de la bdd events peut résoudre comme évènement ou comme annonce
+            if(obj.is_announcement) 
+                return obj;
+            else
+                return null;
+        }
+    },
+
+    Event: {
+
+        startTime : function(obj){
+            return obj.start_time;
+        },
+
+        endTime : function(obj){
+            return obj.end_time;
+        },
+
+        asAnnouncement : function(obj, args, context){
+            // le champ is_announcement indique si il existe une annonce qui va avec l'évènement
+            // une ligne de la bdd events peut résoudre comme évènement ou comme annonce
+            if(obj.is_announcement) 
+                return obj;
+            else
+                return null;
+        }
+    },
+
+    // @rights viewer(obj.uid)
+    Group: {
+        __resolveType: (obj) => {
+            
+            switch(obj.type){
+            case "simple":
+                return "SimpleGroup";
+            case "meta":
+                return "MetaGroup";
+            default:
+                return undefined;
+            }
+        }
+    },
+
+    // @rights viewer(obj.uid)
+    SimpleGroup: {
+        members: (obj, args, context) => {
+            return connectors.listerMembres(context.user,obj.uid);
+        }
+    },
+
+    // @rights viewer(obj.uid)
+    MetaGroup: {
+        members: (obj, args, context) => {
+        }
+    }
+};
diff --git a/src/graphql/schema.js b/src/graphql/schema.js
index 0d96a92c93b7c5b5cedc73eb121e56ed899561a6..720f983a2a8081d20dda52573eebf202740c4697 100644
--- a/src/graphql/schema.js
+++ b/src/graphql/schema.js
@@ -2,249 +2,13 @@
  * @file Ce fichier génère le schéma GraphQL. C'est ici que les requêtes GraphQl sont résolues.
  * @author akka vodol
 */
-import { makeExecutableSchema } from 'graphql-tools';
-import { request } from 'https';
-import { assertBinaryExpression } from 'babel-types';
-import knex from '../../db/knex_router';
-import typeDefs from './typeDefs';
-
-import * as db_utils from './db_utils';
-
-/** 
- * @description Résolveurs des différentes requêtes GraphQL
-*/
-const resolvers = {
-    Query: {
-
-        asAdmin: (obj, args, context) => {
-            return db_utils.hasAdminRights(context.user, args.groupUID).then(res => {
-                if(res)
-                    return {groupUID : args.groupUID};
-                else
-                    throw "You do not have admin rights over this group";
-            });
-        },
-
-        allGroups: (obj, args, context) => {
-            return db_utils.getAllVisibleGroups(context.user);
-        },
-        group: (obj, args, context) => {
-            return db_utils.getGroupIfVisible(context.user, args.uid);
-        },
-        user: (obj, args, context) => {
-            const refactorer = (data) => {
-                return {
-                    uid: args.uid,
-                    lastName: data.sn,
-                    givenName: data.givenName,
-                    birthdate: data.brBirthdate,
-                    groups: data.brMemberOf,
-                    mail: data.mail,
-                    phone: data.telephoneNumber,
-                    room: data.brRoom
-                };
-            };
-
-            const result = db_utils.renseignerSurUtilisateur(context.user, args.uid).then(res => {
-                return refactorer(res[0]);
-            });
-
-            return result;
-        },
-
-        allPosts: (obj, args, context) => {
-            return knex.select().from('posts');
-        },
-        post: (obj, args, context) => {
-            const result = knex.select().from('posts').where('id','=',args.id);
-            return result.then((res) => res[0]);
-        },
-
-        searchTOL: (obj, args, context) => {
-            console.log(args);
-            return db_utils.repliquerTOLdesIds(context.user, {
-                givenName: args.givenName,
-                lastName: args.lastName,
-                nickname: args.nickname,
-                nationality: args.nationality,
-                school: args.school,
-                promotion: args.promotion,
-                groups: args.groups,
-                studies: args.studies,
-                sport: args.sport,
-                phone: args.phone,
-                mail: args.mail,
-                adress: args.adress,
-                ip: args.ip
-            });
-        }
-    },
-
-    AdminQuery: {
-        isAdmin: (obj, args, context) => {
-            return true;
-        },
-
-        allRequests: (obj, args, context) => {
-            console.log(obj);
-            return obj;
-        }
-    },
-
-    AllRequests: {
-        userJoinGroup : (obj, args, context) => {
-            return db_utils.getUserJoinGroupRequests(context.user, args.groupUID);
-        },
-    },
-
-    UserJoinGroup: {
-        user : (obj, args, context) => {
-            return db_utils.getUser(context.user, obj.useruid);
-            /*return db_utils.getUser(context.user, "quentin.gendre");
-            if(obj.useruid === "anatole.romon"){
-                return db_utils.getUser(context.user, "anatole.romon").then(res => {
-                    return db_utils.getUser(context.user, "quentin.gendre");
-                });
-            }else{
-                return new Promise( (resolve, reject) => {
-                    resolve({givenName : "patrick"});
-                });
-            }*/
-        }
-    },
-
-    GroupJoinEvent : {
-        event: (obj, args, context) => {
-            return db_utils.getEvent(context.user, obj.eventuid);
-        },
-        groupWantingToJoin: (obj, args, context) => {
-            return db_utils.getGroup(context.user, obj.senderuid);
-        }
-    },
-
-    YourGroupHostEvent : {
-        event: (obj, args, context) => {
-            return db_utils.getEvent(context.user, obj.eventuid);
-        },
-        sender: (obj, args, context) => {
-            return db_utils.getGroup(context.user, obj.senderuid);
-        }
-    },
-
-    /*User : {
 
-        givenName : (obj, args, context) => {
-            console.log("I got this")
-            return null;
-        },
-
-        lastName : (obj, args, context) => {
-            return null;
-        },
-
-        uid : (obj, args, context) => {
-            return null;
-        },
-
-        birthdate : (obj, args, context) => {
-            return null;
-        },
-
-        mail : (obj, args, context) => {
-            return null;
-        },
-
-        phone : (obj, args, context) => {
-            return null;
-        },
-
-        groups : (obj, args, context) => {
-            return null;
-        },
-
-        likes : (obj, args, context) => {
-            return null;
-        },
-
-        address : (obj, args, context) => {
-            return null;
-        }
-
-    },*/
-
-    Mutation: {
-        asAdmin: (obj, args, context) => {
-            return db_utils.hasAdminRights(context.user, args.groupUID).then(res => {
-                if(res)
-                    return {groupUID : args.groupUID};
-                else
-                    throw "You do not have admin rights over this group";
-            });
-        },
-
-        asSpeaker: (obj, args, context) => {
-            return db_utils.hasAdminRights(context.user, args.groupUID).then(res => {
-                if(res)
-                    return {groupUID : args.groupUID};
-                else
-                    throw "You do not have publishing rights in this group";
-            });
-        },
-
-        asMember: (obj, args, context) => {
-            return db_utils.isMember(context.user, args.groupUID).then(res => {
-                if(res)
-                    return {groupUID : args.groupUID};
-                else
-                    throw "You are  not a member of this group";
-            });
-        },
-        asViewer: (obj, args, context) => {
-            return db_utils.getGroupIfVisible(context.user, args.groupUID).then(res => {
-                if(res)
-                    return {groupUID : args.groupUID};
-                else
-                    throw "You are  not a member of this group";
-            });
-        }
-    },
-
-    AdminMutation: {
-        isAdmin: (obj, args, context) => {
-            return true;
-        
-        },
-        createSubgroup: (obj, args, context) => {
-            args.parentuid = obj.groupUID;
-            return db_utils.createSubgroup(context.user, args);
-        },
-
-        editGroup: (obj, args, context) => {
-            return null;
-        }
-    },
-
-    ViewerMutation: {
-        requestJoin: (obj, args, context) => {
-            console.log(obj);
-            return null;
-        }
-    },
-
-    Post: {
-        authors: (obj, args, context) => {
-            return knex.select().from('groups').whereIn('uid',obj.authors);
-        }
-    },
+import { makeExecutableSchema } from 'graphql-tools';
+import actionDefs from './typeDefs/actions';
+import objectDefs from './typeDefs/objects';
+import { resolvers } from './resolvers';
 
-    Group: {
-        members: (obj, args, context) => {
-            console.log("Current group is",obj.uid);
-            console.log("\tMembers of the group are:",obj);
-            return db_utils.listerMembres(context.user,obj.uid);
-        }
-    }
-};
+const typeDefs = actionDefs.concat(objectDefs);
 
 const schema = makeExecutableSchema({
     typeDefs,
diff --git a/src/graphql/typeDefs/actions.js b/src/graphql/typeDefs/actions.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0d4bd704a4ca6bc3183ec8dc273eae94b16fed4
--- /dev/null
+++ b/src/graphql/typeDefs/actions.js
@@ -0,0 +1,144 @@
+const RootTypes = `
+    # Requêtes
+    type Query {
+        accessGroups : GroupQuery
+        accessPosts : MessageQuery
+        accessUsers : UserQuery
+
+        asAdmin(groupUID: ID): AdminQuery
+        asSpeaker(groupUID: ID): AdminQuery
+        asMember(groupUID: ID): MemberQuery
+        asViewer(groupUID: ID): AdminQuery
+        
+    }
+
+    type Mutation {
+        asSuperviser(groupUID: String): SuperviserMutation
+        asAdmin(groupUID: String): AdminMutation
+        asSpeaker(groupUID: String): SpeakerMutation
+        asMember(groupUID: String): MemberMutation
+        asViewer(groupUID: String): ViewerMutation
+    }
+
+   
+`;
+
+const subMutations = `
+
+    type SuperviserMutation {
+        runAdminOperation : AdminMutation
+        takeAdminRights : Group
+    }
+
+    type AdminMutation {
+
+        isAdmin: Boolean
+
+        createSubgroup(
+            uid: ID = null,
+            name: String,
+            website: String,
+            description: String,
+            school: String
+        ): Group
+
+        addUser(userid : String): User
+        removeUser(userid : String): User
+        addAdmin(userid : String): User
+        removeAdmin(userid : String): User
+
+        editGroup(
+            name: String,
+            website: String,
+            description: String,
+            school: String
+        ): Group
+
+    }
+
+    type SpeakerMutation{
+        postEvent(name: String, date: String): Event
+        answerEventRequest(request: ID, accept : Boolean): Request
+    }
+
+    type MemberMutation {
+        leave: Group
+    }
+
+    type ViewerMutation {
+        requestJoin: Group
+    }
+
+
+`;
+
+const subQueries = `
+
+    """
+    Requête pour obtenir un groupe.
+    """
+    type GroupQuery{
+        allGroups: [Group]
+        allSimpleGroups: [SimpleGroup]
+
+        group(uid: ID) : Group
+        simpleGroup(uid : ID) : SimpleGroup
+        metaGroup(uid : ID) : MetaGroup
+
+    }
+
+    """
+    Requête pour obtenir un message.
+    """
+    type MessageQuery{
+        allMessages: [Message]
+        allEvents: [Event]
+        allPosts: [Post]
+        message(id: ID): Message
+        allAnnouncements: [Announcement]
+    }
+
+    type UserQuery{
+
+        user(uid: ID) : User
+
+        searchTOL(
+            givenName: String,
+            lastName: String,
+            nickname: String,
+            nationality: String,
+            school: String,
+            promotion: String,
+            groups: String,
+            studies: String,
+            sport: String,
+            phone: String,
+            mail: String,
+            adress: String,
+            ip: String
+        ): [String]
+    }
+
+    # Requête à la base de donnée nécessitant d'être administrateur.
+    type AdminQuery{
+        isAdmin: Boolean
+        allRequests : [Request]
+    }
+
+    type SpeakerQuery{
+        isSpeaker: Boolean
+        allRequests : [Request]
+    }
+
+    type MemberQuery{
+        isMember: Boolean
+        allMembers : [Group]
+    }
+
+    type ViewerQuery{
+        isViewer: Boolean
+    }
+`;
+
+const actionDefs = [RootTypes, subQueries, subMutations ];
+export default actionDefs;
diff --git a/src/graphql/typeDefs.js b/src/graphql/typeDefs/objects.js
similarity index 51%
rename from src/graphql/typeDefs.js
rename to src/graphql/typeDefs/objects.js
index 71686030bbe6969b47a8bcf0ed99ae41b5e56387..03b46e5bb12d3e088e7b8c581ed3d932e05a1d93 100644
--- a/src/graphql/typeDefs.js
+++ b/src/graphql/typeDefs/objects.js
@@ -1,109 +1,3 @@
-const RootTypes = `
-    # Requêtes
-    type Query {
-        allGroups: [Group]
-        group(uid: ID) : Group
-        user(uid: ID) : User
-        allMessages: [Message]
-        allEvents: [Event]
-        allPosts: [Post]
-        post(id: ID): Post
-        allAnnouncements: [Announcement]
-
-        asAdmin(groupUID: ID): AdminQuery
-        asSpeaker(groupUID: ID): AdminQuery
-        asMember(groupUID: ID): AdminQuery
-        asViewer(groupUID: ID): AdminQuery
-        
-        searchTOL(
-            givenName: String,
-            lastName: String,
-            nickname: String,
-            nationality: String,
-            school: String,
-            promotion: String,
-            groups: String,
-            studies: String,
-            sport: String,
-            phone: String,
-            mail: String,
-            adress: String,
-            ip: String
-        ): [String]
-    }
-
-    type Mutation {
-        asAdmin(groupUID: String): AdminMutation
-        asSpeaker(groupUID: String): SpeakerMutation
-        asMember(groupUID: String): MemberMutation
-        asViewer(groupUID: String): ViewerMutation
-    }
-
-   
-`;
-
-const subMutations = `
-    type AdminMutation {
-
-        isAdmin: Boolean
-
-        createSubgroup(
-            uid: ID = null,
-            name: String,
-            website: String,
-            description: String,
-            school: String
-        ): Group
-
-        addUser(userid : String): User
-        removeUser(userid : String): User
-        addAdmin(userid : String): User
-        removeAdmin(userid : String): User
-
-        editGroup(
-            name: String,
-            website: String,
-            description: String,
-            school: String
-        ): Group
-
-    }
-
-    type SpeakerMutation{
-        postEvent(name: String, date: String): Event
-        answerRequest(request: ID, accept : Boolean): Request
-    }
-
-    type MemberMutation {
-        leave: Group
-    }
-
-    type ViewerMutation {
-        requestJoin: Group
-    }
-
-
-`;
-
-const subQueries = `
-    # Requête à la base de donnée nécessitant d'être administrateur.
-    type AdminQuery{
-        isAdmin: Boolean
-        allRequests : AllRequests
-    }
-
-    type SpeakerQuery{
-        isSpeaker: Boolean
-    }
-
-    type MemberQuery{
-        isMember: Boolean
-    }
-
-    type ViewerQuery{
-        isViewer: Boolean
-    }
-`;
 
 const User = `
     # Utilisateurs
@@ -112,38 +6,76 @@ const User = `
         givenName: String!
         # Nom de famille
         lastName: String!
+        # Surnom
+        nickname: String
+        nationality: String
         uid: ID!
         birthdate: String!
         mail: String
         phone: String
         # Groupes dont l'utilisateur est membre.
-        groups: [Group]
+        groups: [SimpleGroup]
         # Groupes que l'utilisateur aime.
         likes: [Group]
-        address: String
+        # Adresse(s) de l'utilisateur.
+        address: [String]
+        # Promotion
+        promotion: String
     }
 `;
 
 const Group = `
     # Groupes associatifs
-    type Group {
-        # Identifiant unique du groupe
+
+    """
+    L'interface Group représente les deux types de groupes implémentés dans Sigma : les groupes
+    simples, dont les membres sont des utilisateurs, et les métagroupes, dont les membres sont
+    des groupes simples (tel que Federez, dont les membres incluent le BR et DaTA). 
+    """
+    interface Group {
+        # Identifiant unique de l'union
         uid: ID
-        # Nom du groupe
+        # Nom de l'union
         name: String
         # Site du groupe
         website: String
+        # Le groupe est-il un spiritualGroup (sinon c'est un materialGroup)
+        createdAt: String!
+        updatedAt: String!
+
+    }
+
+    # Le groupe de base, dont les membres sont des utilisateurs. Binets, Kes, etc...
+    type SimpleGroup implements Group{
+        uid: ID
+        name: String
+        website: String
+        createdAt: String!
+        updatedAt: String!
+
         # Membres du groupe
         members: [User]
         # Jour et heure de création du groupe
-        createdAt: String!
-        updatedAt: String!
         description: String
         # École d'origine du groupe
         school: String
         # Groupe parent
         parent: Group
     }
+
+    # Anciennement appelé "interface dans les discussions"
+    # Un groupe dont les membre sont d'autres groupes
+    type MetaGroup implements Group {
+        uid: ID
+        name: String
+        website: String
+        createdAt: String!
+        updatedAt: String!
+
+        # Les groupes constitutifs du méta-groupe.
+        members: [Group]!
+    }
+
 `;
 
 const Message = `
@@ -152,6 +84,7 @@ const Message = `
         id: ID!
         # Titre du message
         title: String!
+        content: String
         createdAt: String!
         updatedAt: String!
         # Auteur(s) du message
@@ -179,8 +112,10 @@ const Announcement = `
         createdAt: String!
         updatedAt: String!
         authors: [Group]
-        description: String!
+        content: String!
+        importance: Int
         views: Int
+        forEvent : Event
     }
 `;
 
@@ -199,18 +134,14 @@ const Event = `
         # Organisateurs
         authors: [Group]
         # Personnes qui participent à l'événement.
-        participants: [User]
-        description: String
+        participatingGroups: [Group]
+        participatingUsers: [User]
+        content: String
+        asAnnouncement : Announcement
     }
 `;
 
 const Requests = `
-    # Demandes effectuées au groupe.
-    type AllRequests {
-        userJoinGroup: [UserJoinGroup]
-        groupJoinEvent: [GroupJoinEvent]
-        yourGroupHostEvent: [YourGroupHostEvent]
-    }
 
     interface Request {
         # ID de la demande
@@ -250,5 +181,5 @@ const Requests = `
 
 `;
 
-const typeDefs = [RootTypes, Group, User, Message, Post, Announcement, Event, subMutations, subQueries, Requests];
-export default typeDefs;
+const objectDefs = [Group, User, Message, Post, Announcement, Event, Requests];
+export default objectDefs;
\ No newline at end of file
diff --git a/src/ldap/ldap_data.js b/src/ldap/ldap_data.js
index a16121ac409b7b59a10be116215bdf03d32d2ca7..799168066221d1676a9b8537747479ef22ed1dce 100644
--- a/src/ldap/ldap_data.js
+++ b/src/ldap/ldap_data.js
@@ -1,5 +1,9 @@
 /**
- * @file Ce fichier gère les requêtes LDAP de type données ; liste des groupe d'un individu, liste des membres d'un groupe... A ne pas confondre avec ldap_auth qui lui gère l'authentification. Il est à lire conjointement avec config.json qui détaille les paxs et champs spécifique à un LDAP. Il est fortement conseillé d'utiliser [`JXplorer`](http://jxplorer.org/) pour baviguer sur le LDAP en parallèle du dévelopement.
+ * @file Ce fichier gère les requêtes LDAP de type données ; liste des groupe d'un individu, liste des membres d'un groupe...
+ * A ne pas confondre avec ldap_auth qui lui gère l'authentification. Il est à lire conjointement avec [`ldap_config.json`](..\..\config.json) qui détaille
+ * les champs spécifiques à chaque LDAP, anonymisés ici.  Il est fortement conseillé d'utiliser [`JXplorer`](http://jxplorer.org/) pour naviguer sur le LDAP
+ * en parallèle du dévelopement. Toutes les fonctions écrites ici sont asynchrones et renvoient des Promises ce qui nécessite de les appeler avec la synthaxe
+ * un peu particulière `f(args).then(res => ...)` pour exploiter leur résultat.
  * @author hawkspar
  */
 
@@ -32,42 +36,32 @@ var client = ldap.createClient({ url: config.ldap.server});
 //------------------------------------------------------------------------------------------------------------------------
 
 /**
- * @summary Fonction qui sert à s'identifier sur le LDAP. Renvoit rien.
+ * @summary Fonction qui sert à s'identifier sur le LDAP. Ne renvoie rien.
  * @desc Assez important en terme de sécurité, de gestion de conflit, et de droit d'accès. Méthode ldapjs 
  * (voir [`Client API`](http://ldapjs.org/client.html) méthode bind).
  * @arg {Object} user - Utilisateur de la forme suivante :
  * @arg {string} user[uid] - User identifier
  * @arg {string} user[password] - Mot de passe
 */
-function connecterLDAP(user) {
-    // TBM utiliser user
-    client.bind(connect.dn, connect.passwd, (err, res) => {});
-}
+function connecterLDAP(user) { client.bind(connect.dn, connect.passwd, (err, res) => {}); } // TBM utiliser user 
 
 /**
  * @summary Fonction qui interroge le LDAP selon un protocole spécifié en argument et renvoit les valeurs trouvées.
- * @desc Cette fonction appelle {@link bind} pour authentifier l'utilisateur pour authentifier l'utilisateur
- * puis rompt la connexion. Cette fonction utilise une Promise pour être asynchrone ; elle renvoie la promesse 
- * d'une réponse puis traite la demande avec [`ldapjs`](http://ldapjs.org) 
- * (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant 
- * un schéma `rechercherLDAP(user, ...).then((res) => { truc avec res });`. Cette fonction fait une demande 
- * au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met 
- * dans une liste, et renvoit la liste à l'issue (event end).
+ * @desc Cette fonction appelle {@link bind} pour authentifier l'utilisateur pour authentifier l'utilisateur puis rompts la connexion.
+ * Cette fonction utilise ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant un schéma
+ * `rechercherLDAP(user, ...).then((res) => { truc avec res });`. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic`
+ * et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
  * @arg {string} base - DN de l'emplacement de la requête
- * @arg {string} filter - Filtre logique de la recherche (format [`RFC2254`](https://tools.ietf.org/search/rfc2254)) déjà passé au ldapEscape
+ * @arg {string} filter ["(objectClass=*)"] - Filtre logique de la recherche (format [`RFC2254`](https://tools.ietf.org/search/rfc2254)) déjà passé au ldapEscape
  * @arg {string} filter_dic[key] - Vraie valeur pertinente de la recherche
  * @arg {string[]} attributes - Liste des attributs qui figureront dans le résultat final
  * @return {Promise(Object[])} Résultats de la recherche ; soit une liste de valeurs d'attributs, 
  * soit une liste de dictionnaires si on veut plus d'un attribut (les clés du dictionnaire sont celles du LDAP) 
  */
-function rechercherLDAP(user, base, filter, attributes) {
-    return new Promise(function(resolve, reject) {
+function rechercherLDAP(user, base, attributes, filter="(objectClass=*)") {
+    return new Promise((resolve, reject) => {
         connecterLDAP(user);
-        //Debug
-        /*console.log(base);
-        console.log(filter);
-        console.log(attributes);*/
 
         let vals=[];
         // Interrogation LDAP selon configuration fournie en argument
@@ -103,23 +97,28 @@ function rechercherLDAP(user, base, filter, attributes) {
     });
 }
 
+//TBT
 /**
  * @summary Fonction qui permet de modifier un élément sur le LDAP. Gestion intelligente de l'appartenance à un binet.
- * @desc Cette fonction appelle {@link bind} pour authentifier l'utilisateur pour authentifier l'utilisateur puis rompts la connexion. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode modify). Il faut l'appeler suivant un schéma `modifierLDAP(...).then((res) => { truc avec res });`. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @desc Cette fonction appelle {@link bind} pour authentifier l'utilisateur pour authentifier l'utilisateur puis rompts la connexion.
+ * Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs
+ * (voir [`Client API`](http://ldapjs.org/client.html) méthode modify). Il faut l'appeler suivant un schéma `modifierLDAP(...).then((res) => { truc avec res });`.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
  * @arg {string} name - DN de l'endroit à modifier
- * @arg {string} op - Operation à réaliser sur le LDAP. Trois opération sont possibles ; "add", qui rajoute des attributs et qui peut créer des doublons, "del" qui en supprime, et "replace" qui remplace du contenu par un autre. 
- * @arg {Object} mod - Dictionnaire contenant les attributs à modifier et les nouvelles valeurs des attributs. Une nouvelle valeur vide ("") est équivalent à la suppression de cet attribut.
+ * @arg {string} op - Operation à réaliser sur le LDAP. Trois opération sont possibles ; "add", qui rajoute des attributs et qui peut créer des doublons,
+ * "del" qui en supprime, et "replace" qui remplace du contenu par un autre. 
+ * @arg {Object} mod - Dictionnaire contenant les attributs à modifier et les nouvelles valeurs des attributs. Une nouvelle valeur vide ("") est équivalent à la suppression
+ * de cet attribut.
  * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
  */
 function modifierLDAP(user, name, op, mod) {
-    return new Promise(function(resolve, reject) {
+    return new Promise((resolve, reject) => {
         connecterLDAP(user);
         // Modification LDAP selon configuration en argument (pourrait prendre une liste de Changes)
         client.modify(name, new ldap.Change({
             operation: op,
             modification: mod,
-        }), function(err) {
+        }), err => {
             reject(err);
         });
         client.bind("", "", (err, res) => {});
@@ -127,9 +126,12 @@ function modifierLDAP(user, name, op, mod) {
     });
 }
 
+//TBT
 /**
  * @summary Fonction qui permet de rajouter un élément sur le LDAP.
- * @desc Cette fonction appelle {@link connecterLDAP} pour authentifier l'utilisateur puis rompts la connexion. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode add). Il faut l'appeler suivant un schéma `modifierLDAP(...).then((res) => { truc avec res });`. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @desc Cette fonction appelle {@link connecterLDAP} pour authentifier l'utilisateur puis rompts la connexion. Cette fonction utilise une Promise pour être asynchrone ;
+ * elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode add).
+ * Il faut l'appeler suivant un schéma `modifierLDAP(...).then((res) => { truc avec res });`.
  * @arg {Object} user - Utilisateur de la forme nécessaire au {@link connecterLDAP}
  * @arg {string} dn - Adresse du parent
  * @arg {Object} vals - Dictionnaire contenant les valeurs à créer
@@ -137,10 +139,34 @@ function modifierLDAP(user, name, op, mod) {
  * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
  */
 function ajouterLDAP(user, dn, vals) {
-    return new Promise(function(resolve, reject) {
+    return new Promise((resolve, reject) => {
         connecterLDAP(user);
         // Ajout LDAP selon la configuration en argument
-        client.add(config.key_id+"="+vals["uid"]+","+dn, vals, function(err) {
+        client.add(config.key_id+"="+vals[config.key_id]+","+dn, vals, function(err) {
+            reject(err);
+        });
+        client.bind("", "", (err, res) => {});
+        resolve(true);
+    });
+}
+
+//TBT
+/**
+ * @summary Fonction qui permet de supprimer une feuille du LDAP.
+ * @desc Cette fonction appelle {@link connecterLDAP} pour authentifier l'utilisateur puis rompts la connexion. Cette fonction utilise une Promise pour être asynchrone ;
+ * elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode del).
+ * Il faut l'appeler suivant un schéma `modifierLDAP(...).then((res) => { truc avec res });`. Cette fonction fait une demande au LDAP qu'elle filtre selon un
+ * schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * Elle est différente de modify avec "del" car elle affecte directement une feuille et pas un attribut.
+ * @arg {Object} user - Utilisateur de la forme nécessaire au {@link connecterLDAP}
+ * @arg {string} dn - Adresse de la cible
+ * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
+ */
+function supprimerLDAP(user, dn) {
+    return new Promise((resolve, reject) => {
+        connecterLDAP(user);
+        // Suppression LDAP
+        client.del(dn, function(err) {
             reject(err);
         });
         client.bind("", "", (err, res) => {});
@@ -153,85 +179,94 @@ function ajouterLDAP(user, dn, vals) {
 //------------------------------------------------------------------------------------------------------------------------
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre.
- * @desc Cette fonction utilise {@link rechercherLDAP} avec un dictionnaire prédéfini dans config.json, entrée lg. 
- * Il faut l'appeler selon un schéma 
- * `listGroups(...).then((res) => { truc avec res });`. Elle utilise LDAPEscape pour éviter les injections.
+ * @summary Fonction qui retrouve les groupes dont un individu est membre.
+ * @desc Cette fonction utilise {@link rechercherLDAP} ; elle va directement à la feuille de l'utilisateur 
+ * et n'a donc pas de filtre. Elle utilise ldapEscape pour éviter les injections.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
  * @arg {string} uid - Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide)
  * @return {Promise(string[])} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
  */
 function listerGroupes(user, uid) {
-    return new Promise(function(resolve, reject) {
-        rechercherLDAP(user,config.key_id+"="+uid+","+config.dn_users, ldapEscape.filter(config.lg.filtre, { id : uid }), config.lg.attributs)
-            .then(res => resolve(res[0]));
+    return new Promise((resolve, reject) => {
+        rechercherLDAP(user,ldapEscape.filter(config.key_id+"=${id},"+config.dn_users, {id : uid}), config.user.groups).then(res => resolve(res[0]));
     });
 }
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve la liste des membres d'un groupe.
- * @desc Cette fonction utilise {@link rechercherLDAP} avec un dictionnaire prédéfini dans config.json.
- * Il faut l'appeler selon un schéma `listMembers(...).then((res) => { truc avec res });`. Elle utilise LDAPEscape pour éviter les injections.
+ * @summary Fonction qui retrouve la liste des membres d'un groupe.
+ * @desc Cette fonction utilise {@link rechercherLDAP} avec un dictionnaire prédéfini dans config.json. 
+ * Elle utilise LDAPEscape pour éviter les injections.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
  * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)
- * @return {Promise(string[])} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
+ * @return {Promise(String[])} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
  */
 function listerMembres(user, gid) {
-    return new Promise(function(resolve, reject) {
-        rechercherLDAP(user, config.key_id+"="+gid+","+config.dn_groups, ldapEscape.filter(config.lm.filtre, { id: gid }), config.lm.attributs)
-            .then(res => resolve(res[0]));
+    return new Promise((resolve, reject) => {
+        rechercherLDAP(user,ldapEscape.filter(config.key_id+"=${id},"+config.dn_users, {id : gid}), config.group.member).then(res => resolve(res[0]));
     });
 }
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve la liste des admins d'un groupe.
+ * @summary Fonction qui retrouve la liste des admins d'un groupe.
  * @desc Cette fonction utilise {@link rechercherLDAP} avec un dictionnaire prédéfini dans config.json. 
- * Il faut l'appeler selon un schéma `listAdmins(...).then((res) => { truc avec res });`. Elle utilise LDAPEscape pour éviter les injections.
+ * Elle utilise LDAPEscape pour éviter les injections.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
  * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)
  * @return {Promise(string[])} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
  */
 function listerAdministrateurs(user, gid) {
-    return new Promise(function(resolve, reject) {
-        rechercherLDAP(user, config.key_id+"="+gid+","+config.dn_groups, ldapEscape.filter(config.la.filtre, { id: gid }), config.la.attributs)
-            .then(res => resolve(res[0]));
+    return new Promise((resolve, reject) => {
+        rechercherLDAP(user,ldapEscape.filter(config.key_id+"=${id},"+config.dn_users, {id : gid}), config.group.admin).then(res => resolve(res[0]));
     });
 }
  
 /**
- * @summary Fonction qui interroge le LDAP au sujet d'un uid particulier et qui renvoit toutes ses infos.
- * @desc Cette fonction utilise {@link rechercherLDAP} avec un dictionnaire prédéfini dans config.json. 
- * Il faut l'appeler selon un schéma `rens(...).then((res) => { truc avec res });`. Elle utilise LDAPEscape pour éviter les injections.
+ * @summary Fonction qui renvoit toutes les infos relatives à un utilisateur particulier.
+ * @desc Cette fonction utilise {@link rechercherLDAP} avec des attributs prédéfinis. Elle utilise LDAPEscape pour éviter les injections.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
  * @arg {string} uid - Identifiant de l'utilisateur
- * @return {Promise(Object[])} Informations recueillies ; renvoie une liste de dictionnaire avec les mêmes clés que dans le TOL, voir config.json.
+ * @return {Promise(Object[])} Informations recueillies ; renvoie une liste de dictionnaire avec le profil complet de l'utilisateur ;
+ * voir `ldap_config.json`(..\..\ldap_config.json) pour les clés exactes.
  */
 function renseignerSurUtilisateur(user, uid) {
-    return new Promise(function(resolve, reject) {
-        rechercherLDAP(user, config.key_id+"="+uid+","+config.dn_users, ldapEscape.filter(config.rs.filtre, { id: uid }), config.rs.attributs)
+    return new Promise((resolve, reject) => {
+        rechercherLDAP(user,ldapEscape.filter(config.key_id+"=${id},"+config.dn_users, {id : uid}), config.user.profil)
             .then(res => resolve(res));
     });
 }
+ 
+/**
+ * @summary Fonction qui renvoit toutes les infos relatives à un groupe particulier.
+ * @desc Cette fonction utilise {@link rechercherLDAP} avec des attributs prédéfinis. Elle utilise LDAPEscape pour éviter les injections.
+ * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
+ * @arg {string} gid - Identifiant du groupe
+ * @return {Promise(Object[])} Informations recueillies ; renvoie une liste de dictionnaire avec le profil complet du groupe ;
+ * voir `ldap_config.json`(..\..\ldap_config.json) pour les clés exactes.
+ */
+function renseignerSurGroupe(user, gid) {
+    return new Promise((resolve, reject) => {
+        rechercherLDAP(user,ldapEscape.filter(config.key_id+"=${id},"+config.dn_groups, {id : gid}), config.group.profil).then(res => resolve(res));
+    });
+}
 
 //------------------------------------------------------------------------------------------------------------------------
 // Fonctions de recherche
 //------------------------------------------------------------------------------------------------------------------------
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve les groupes (voir LDAP) qui ressemblent à l'input. 
- * Etape 0 vers un vrai TOL (Trombino On Line).
+ * @summary Fonction qui interroge le LDAP et retrouve les groupes (voir LDAP) qui ressemblent
+ *  à l'entrée. Etape 0 vers un vrai TOL (Trombino On Line).
  * @desc Cette fonction utilise {@link rechercherLDAP} mais avec un filtre généré à la volée. 
- * Accepte des champs exacts ou incomplets mais pas approximatifs et ne gère pas l'auto-complete. 
- * Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis 
- * traite la demande. Il faut l'appeler suivant un schéma `trouverGroupe(user, input).then((res) => { truc avec res });`. 
- * Cette fonction utilise aussi config.json. MEF Timeout pour des recherches trop vagues. Renvoit une liste d'uid. 
+ * Accepte des champs exacts ou incomplets mais pas approximatifs
+ * et ne gère pas l'auto-complete. Cette fonction utilise aussi config.json. MEF Timeout pour
+ * des recherches trop vagues. Renvoit une liste d'uid.
  * Elle utilise LDAPEscape pour éviter les injections.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
  * @arg {string} input - String entré par l'utilisateur qui ressemble au nom du groupe.
  * @return {Promise(string[])} Liste des uid de groupes dont le nom ressemble à l'input
  */
 function trouverGroupes(user, input) {
-    return new Promise(function(resolve, reject) {
+    return new Promise((resolve, reject) => {
         // Escape de l'input utilisateur par sécurité
         let str=ldapEscape.filter("${txt}", { txt: input});
 
@@ -242,35 +277,38 @@ function trouverGroupes(user, input) {
                     "("+config.key_id+"="+str+"*))))";   // La valeur du début avec des trucs après
 
         // Appel rechercheLDAP avec filtre de l'espace 
-        rechercherLDAP(user, config.dn_groups, filter, config.key_id).then(res => resolve(res));
+        rechercherLDAP(user, config.dn_groups, config.key_id, filter).then(res => resolve(res));
     });
 }
 
+// TBT
 /**
  * @summary Fonction qui interroge le LDAP et retrouve le groupe qui ressemblent à l'input et qui correspond. 
  * Etape 0 vers un vrai TOL (Trombino On Line).
- * @desc Cette fonction utilise {@link rechercherLDAP} mais avec un filtre généré à la volée. Accepte des 
- * champs exacts ou incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise 
- * une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut 
- * l'appeler suivant un schéma `trouverGroupe(user, input).then((res) => { truc avec res });`. Cette fonction 
- * utilise aussi config.json. MEF Timeout pour des recherches trop vagues. Renvoit une liste d'uid. Elle utilise 
- * LDAPEscape pour éviter les injections.
+ * @desc Cette fonction utilise {@link rechercherLDAP} mais avec un filtre généré à la volée. 
+ * Accepte des champs exacts ou incomplets mais pas approximatifs et
+ * ne gère pas l'auto-complete. Cette fonction utilise aussi config.json. MEF Timeout pour des recherches trop vagues. 
+ * Renvoie une liste d'uid. Elle utilise LDAPEscape
+ * pour éviter les injections.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
  * @arg {string} input - String entré par l'utilisateur qui ressemble au nom du groupe.
  * @arg {string} type - String aux valeurs prédéfinies dans ldap_config.
  * @return {Promise(string[])} Liste des uid de groupes dont le nom ressemble à l'input
 */
 function trouverGroupesParTypes(user, input, type) {
-    return new Promise(function(resolve, reject) {
+    return new Promise((resolve, reject) => {
         // Appels imbriqués
         trouverGroupes(user, input).then(gidList => {
             let gidtyList = [];
             gidList.forEach(gid => {
-                // Nouvelle recherche à partir des résultats de la première
-                rechercherLDAP(config.key_id+"="+gid+","+config.dn_groups, ldapEscape.filter(config.tgty.filter, { ty: type }), config.key_id)
-                    .then(res => {
-                        if (res.length!=0) { gidtyList.push(res); }
-                    });
+                // Nouvelle recherche à partir des résultats de la première ; pour chaque groupe 
+                // qui correspond on vérifie que son type est celui attendu
+                let base = ldapEscape.filter(config.key_id+"=${id},"+config.dn_groups, {id : gid} );
+                let attribute = config.key_id;
+                let filter = ldapEscape.filter("("+config.groups.type+"=${ty})", { ty: type });
+                rechercherLDAP(base, attribute, filter).then(res => {
+                    if (res.length!=0) { gidtyList.push(res); }
+                });
             });
             resolve(gidtyList);
         });
@@ -278,35 +316,44 @@ function trouverGroupesParTypes(user, input, type) {
 }
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve certains attributs des paxs validant les critères de 
- * recherche. Première étape vers vrai TOL (Trombino On Line).
- * @desc Cette fonction utilise {@link rechercherLDAP} mais avec un filtre généré à la volée. Accepte des champs 
- * exacts ou incomplets pour la plupart des champs mais pas approximatifs et ne gère pas l'auto-complete. Cette 
- * fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. 
- * Il faut l'appeler suivant un schéma `TOL(uid).then((res) => { truc avec res });`.Cette fonction fait une demande 
- * au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) 
- * le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues. Renvoie 
- * aussi une liste de dictionnaire. Elle utilise LDAPEscape pour éviter les injections.
+ * @summary Fonction qui renvoit les attributs demandés des paxs validant les critères de recherche. 
+ * Première étape vers vrai TOL (Trombino On Line).
+ * @desc Cette fonction utilise {@link rechercherLDAP} mais avec un filtre généré à la volée. 
+ * Accepte des champs exacts ou incomplets pour la plupart des champs
+ * mais pas approximatifs et ne gère pas l'auto-complete. MEF Timeout pour des recherches 
+ * trop vagues. Elle utilise LDAPEscape pour éviter les injections.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
- * @arg {Object} data - Dictionnaire contenant les données nécessaires à la recherche  avec des champs lisibles (voir config).
- * @arg {string} data[key] - La plupart des champs sont directement des string.
- * @arg {string[]} data[key] - Mais certains des champs peuvent être des listes, permettant une recherche sur plusieurs valeurs du même critère.
- * @arg {string[]} return_values - Liste d'attributs à renvoyer
- * @return {string[]} Attributs des profils qui "match" les critères proposés.
+ * @arg {Object} data - Dictionnaire contenant les données nécessaires à la recherche. Les valeurs sont celles entrées par l'utilisateur et sont par hypothèse
+ * comme des sous-parties compactes des valeurs renvoyées. Tous les champs ci-dessous peuvent être indifféremment des listes (par exempl pour chercher un membre
+ * de plusieurs groupes) ou des éléments isolés. Si un champ n'est pas pertinent, le mettre à '' ou undefined.
+ * @arg {string} data[givenName] - Prénom 
+ * @arg {string} data[lastName] - Nom
+ * @arg {string} data[nickname] - Surnom
+ * @arg {string} data[nationality] - Nationalité (non implémentée pour l'instant, pas de format spécifique)
+ * @arg {string} data[promotion] - String de l'année de promo
+ * @arg {string} data[phone] - String du numéro de portable
+ * @arg {string} data[mail] - Adresse mail
+ * @arg {string} data[ips] - Une ou des adresses ip
+ * @arg {string} data[school] - Ecole d'appartenance (pour l'instant instable)
+ * @arg {string} data[groups] - Un ou plusieurs groupes (pas de différence entre membre simple et admin)
+ * @arg {string} data[studies] - PA ou autre
+ * @arg {string} data[sport] - Section sportive ou autre
+ * @arg {string[]} return_values - Liste d'attributs à renvoyer dans le résultat final
+ * @return {Promise(Object[])} Liste de dictionnaires de profils en cohérence avec l'input avec pour clés les attributs des profils.
  */
 function repliquerTOLModulable(user, data, return_values) {
-    return new Promise(function(resolve, reject) {
+    return new Promise((resolve, reject) => {
         let filter="";
-        // Iteration pour chaque champ, alourdissement du filtre selon des trucs prédéfini dans config.json encore
-        config.tolm.input_names.forEach(name => {
-            if ((data[name]!= undefined) & (data[name] != '')) {                    // Si il y a qque chose à chercher pour ce filtre
-                if (!Array.isArray(data[name])) { data[name]=[data[name]]; }    // Gestion d'une liste de valeurs à rechercher
+        // Iteration pour chaque champ, alourdissement du filtre selon des trucs prédéfinis dans config encore
+        for (var key in data) {
+            if ((data[key]!= undefined) & (data[key] != '')) {                    // Si il y a qque chose à chercher pour ce filtre
+                if (!Array.isArray(data[key])) { data[key]=[data[key]]; }        // Gestion d'une liste de valeurs à rechercher
                 // Iteration pour chaque valeur fournie par l'utilisateur
-                data[name].forEach(val => {
+                data[key].forEach(val => {
                     // Escape de l'input utilisateur
                     let str=ldapEscape.filter("${input}", { input: val});
                     // Traduction en language LDAP
-                    let attribute = config.tolm.correspondance[name];
+                    let attribute = config.user[key];
                     // Creation du filtre étape par étape
                     filter="(&"+filter+ "(|("+attribute+"="+str+")"+      // On cherche la valeur exacte
                                         "(|("+attribute+"=*"+str+")"+     // La valeur finale avec des trucs avant ; wildcard * (MEF la wildcart ne marche pas pour tous les attributs)
@@ -314,167 +361,569 @@ function repliquerTOLModulable(user, data, return_values) {
                                         "("+attribute+"="+str+"*)))))";   // La valeur du début avec des trucs après
                 });
             }
-        });
+        }
         // Appel rechercheLDAP avec filtre de l'espace 
-        rechercherLDAP(user, config.dn_users, filter, return_values).then(res => resolve(res));
+        rechercherLDAP(user, config.dn_users, return_values, filter).then(res => resolve(res));
     });
 }
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve les uid des paxs validant les critères de recherche. 
- * Première étape vers vrai TOL (Trombino On Line).
- * @desc Cette fonction utilise {@link repliquerTOLModulable} mais avec un filtre généré à la volée. Accepte 
- * des champs exacts ou incomplets pour la plupart des champs mais pas approximatifs et ne gère pas l'auto-complétion. 
- * Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la 
- * demande. Il faut l'appeler suivant un schéma `TOL(uid).then((res) => { truc avec res });`.Cette fonction fait une 
- * demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat 
- * (event `SearchEntry`) le met dans une liste, et renvoit la liste à l'issue (event `end`). MEF Timeout pour des recherches trop vagues. 
- * Renvoie aussi une liste de dictionnaire. Elle utilise LDAPEscape pour éviter les injections.
+ * @summary Fonction qui retrouve les uid des paxs validant les critères de recherche. Autre étape vers vrai TOL (Trombino On Line). Doit être préféré à repliquerTOL
+ * car moins gourmande envers le LDAP (utiliser {@link renseignerSurUtilisateur} au cas par cas après pour obtenir les vraies infos).
+ * @desc Cette fonction utilise {@link repliquerTOLModulable}.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
- * @arg {Object} data - Dictionnaire contenant les données nécessaires à la recherche  avec des champs lisibles (voir config).
- * @arg {string} data[key] - La plupart des champs sont directement des string.
- * @arg {string[]} data[key] - Mais certains des champs peuvent être des listes, permettant une recherche sur plusieurs valeurs du même critère.
- * @arg {string[]} return_values - Liste d'attributs à renvoyer
- * @return {string[]} uids des profils qui "match" les critères proposés.
+ * @arg {Object} data - Dictionnaire contenant les données nécessaires à {@link repliquerTOLModulable}
+ * @return {Promise(string[])} uids des profils qui "match" les critères proposés.
  */
 function repliquerTOLdesIds(user, data) {
-    return new Promise( function(resolve, reject) {
+    return new Promise((resolve, reject) => {
         repliquerTOLModulable(user, data, config.key_id).then(res => resolve(res));
     });
 }
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche. 
- * Bien mais vite inutilisable car demande trop au LDAP et renvoie des erreurs de type size limit. 
- * Préférer idTOL puis stalk au cas par cas.
- * @desc Cette fonction utilise {@link repliquerTOLModulable} avec un filtre généré à la volée. Accepte 
- * des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise 
- * une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il 
- * faut l'appeler suivant un schéma `TOL(uid).then((res) => { truc avec res });`. Aucun bind n'est 
- * nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au 
- * LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat 
- * (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout 
- * pour des recherches trop vagues. Renvoit aussi une liste de dictionnaire. Utilise aussi requeteLDAP. 
- * Elle utilise LDAPEscape pour éviter les injections.
+ * @summary Fonction qui retrouve les paxs validant les critères de recherche. Bien mais vite inutilisable car demande trop au LDAP et renvoie des erreurs de type size limit.
+ * Préférer {@link repliquerTOLdesIds} puis {@link renseignerSurUtilisateur} au cas par cas.
+ * @desc Cette fonction utilise {@link repliquerTOLModulable} avec un filtre généré à la volée. Accepte des champs incomplets mais pas approximatifs et ne gère pa
+ * l'auto-complete.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
- * @arg {string} c0 - Prénom
- * @arg {string} c1 - Nom
- * @arg {string} c2 - Surnom
- * @arg {string} c3 - Nationalité
- * @arg {string} c4 - Ecole ou université d'origine
- * @arg {string} c5 - Promotion
- * @arg {string} c6 - Groupe
- * @arg {string} c7 - Cours
- * @arg {string} c8 - Sport pratiqué
- * @arg {string} c9 - Numéro de téléphone
- * @arg {string} c10 - Adresse courriel
- * @arg {string} c11 - Adresse physique
- * @arg {string} c12 - Adresse ip
- * @return {string[]} Informations recueillies ; voir config.json.
+ * @arg {Object} data - Dictionnaire contenant les données nécessaires à {@link repliquerTOLModulable}
+ * @return {Promise(Object[])} Liste de dictionnaires de profils en cohérence avec l'input avec pour clés tous les attributs disponibles ou presque (voir config).
  */
 function repliquerTOL(user, data) {
-    return new Promise( function(resolve, reject) {
-        repliquerTOLModulable(user, data, config.tol.attributes).then(res => resolve(res));
+    return new Promise((resolve, reject) => {
+        repliquerTOLModulable(user, data, config.user.profil).then(res => resolve(res));
+    });
+}
+
+//------------------------------------------------------------------------------------------------------------------------
+// Fonctions intermédiaires TBT
+//------------------------------------------------------------------------------------------------------------------------
+
+/**
+ * @summary Cette fonction teste une valeur d'un attribut (typiquement un identifiant) et le fait évoluer jusqu'à ce qu'il soit unique.
+ * @desc Librement adapté de Stack Overflow. Appelle {@link rechercherLDAP} pour vérifier 
+ * qu'il n'y a pas d'autres occurences de cette valeur pour cette attribut
+ * dans le dn fourni.
+ * @param {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}.
+ * @param {string} valeur - Valeur de l'attribut (le plus souvent un identifiant) à tester à cette itération
+ * @param {string} attribut - Attribut à tester
+ * @param {string} dn - *Domain Name* dans lequel l'attribut doit être unique
+ * @param {function} evoluerValeur - Fonction qui prend uniquement en argument l'id courant et 
+ * le nombre d'itérations et qui renvoit la prochaine valeur de l'attribut 
+ * @param {int} n [0] - Nombre d'itérations (à initialiser à 0)
+ * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié
+ */
+function assurerUnicite(user, valeur, attribut, dn, evoluerValeur, n=0) {
+    return new Promise((resolve, reject) => { 
+        // Recherche d'autres occurences de l'id
+        rechercherLDAP(user, dn, config.key_id, "("+attribut+"="+valeur+")").then(matches => {
+            // On renvoit la valeur si elle est bien unique
+            if (matches.length==0) { resolve(valeur); }
+            // Sinon, on tente de nouveau notre chance avec la valeur suivante
+            else { resolve(assurerUnicite(user, evoluerValeur(valeur, n+1), dn, evoluerValeur, n+1)); }
+        });
+    });
+}
+
+/**
+ * @summary Cette fonction génère un uid standard, puis le fait évoluer jusqu'à ce qu'il soit unique.
+ * @desc Limité à un appel à {@link assurerUnicite} avec les bons paramètres, et quelques opérations 
+ * sur l'uid pour qu'il soit valide (escape, normalisation).
+ * @param {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}.
+ * @param {string} givenName - Prénom
+ * @param {string} lastName - Nom
+ * @param {string} promotion - Année de promotion
+ * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié
+ */
+function genererUid(user, givenName, lastName, promotion) {
+    // Le filtrage évite l'injection de code dans le LDAP, le normalize et lowerCase standardisent le format
+    return new Promise((resolve, reject) => {
+        assurerUnicite(user, ldapEscape.filter("${uid}",{uid: givenName+'.'+lastName}).toLowerCase().normalize('UFD'), config.key_id, config.dn_users, (id,n) => {
+            if (n==1) { id+='.'+ldapEscape.filter("${pr}",{pr: promotion}); }   // Si prénom.nom existe déjà, on rajoute la promo
+            else if (n==2) { id+='.'+n-1; }                                     // Puis si prénom.nom.promo existe déjà on passe à nom.prenom.promo .1
+            else if (n>2) { id+=+n; }                                           // Ensuite on continue .23, .234, etc...
+            return id;
+        }).then(id => resolve(id));
+    });
+}
+
+/**
+ * @summary Cette fonction génère un gid standard, puis le fait évoluer jusqu'à ce qu'il soit unique.
+ * @desc Limité à un appel à {@link assurerUnicite} avec les bons paramètres, et quelques opérations
+ * sur l'uid pour qu'il soit valide (escape, normalisation).
+ * @param {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}.
+ * @param {string} name - Nom
+ * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié
+ */
+function genererGid(user, name) {
+    // Le filtrage évite l'injection de code dans le LDAP, le normalize et lowerCase standardisent le format
+    return new Promise((resolve, reject) => {
+        assurerUnicite(user, ldapEscape.filter("${id}",{id: name}).toLowerCase().normalize('UFD'), config.key_id, config.dn_groups, (id,n) => {
+            if (n==1) { id+='.'+n; }    // Si nom existe déjà, on essaie nom.1
+            else if (n>1) { id+=+n; }   // Ensuite on continue .12, .123, etc...
+            return id;
+        }).then(id => resolve(id));
     });
 }
 
+/**
+ * @summary Cette fonction teste une valeur dummy (0) pour un identifiant numérique puis le fait évoluer aléatoirement (entre 1 et 100 000) jusqu'à ce qu'il soit unique.
+ * @desc Limité à un appel à {@link assurerUnicite} avec les bons paramètres.
+ * @param {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}.
+ * @param {string} attribut - Intitulé exact de l'id concerné
+ * @param {string} dn - *Domain Name* dans lequel l'attribut doit être unique
+ * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié
+ */
+function genererIdNum(user, attribut, dn) {
+    return new Promise((resolve,reject) => { assurerUnicite(user, "0", attribut, dn, (id,n) => { Math.floor((Math.random() * 100000) + 1).toString(); }).then(id => resolve(id)); });
+}
+
 //------------------------------------------------------------------------------------------------------------------------
-// Fonctions de création
+// Fonctions de création TBT
 //------------------------------------------------------------------------------------------------------------------------
 
 /**
- * @summary Fonction qui va plonger dans le LDAP et modifier un certain jeu de valeurs en argument.
- * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une 
- * réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode add). 
- * Il faut l'appeler suivant un schéma `creerUtilisateur(...).then((res) => { truc avec res });`. Cette fonction 
- * fait une utilisation massive d'eval pour anonymiser son code ; c'est mal et cela suppose que beaucoup de soins 
- * ont été pris lors de l'escape de ses paramètres.
+ * @summary Fonction qui créé un nouvel utilisateur dans le LDAP.
+ * @desc Appelle {@link ajouterLDAP} bien sûr, mais aussi {@link ajouterMembreGroupe} et {@link ajouterAdministrateurGroupe} pour gérer les groupes du nouvel utilisateur.
+ * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}.
+ * @arg {Object} data - Dictionnaire des informations utilisateurs. Des erreurs peuvent apparaître si tous les champs ne sont pas remplis.
+ * @arg {string} data[givenName] - Prénom
+ * @arg {string} data[lastName] - Nom
+ * @arg {string} data[nickname] [] - Surnom
+ * @arg {string} data[birthdate] - Date d'anniversaire au format annee-mois-jour
+ * @arg {string} data[password] - Mot de passe
+ * @arg {string} data[promotion] - Simple année d'entrée école (pas d'X17)
+ * @arg {string} data[mail] - Courriel supposé valide
+ * @arg {string} data[phone] - String du numéro de portable
+ * @arg {string} data[photo] - Photo jpeg directement en bytestring
+ * @arg {string} data[room] - Pour l'instant juste le numéro de casert ou rien, à terme l'adresse complète
+ * @arg {string} data[readPerm] [] - Permissions spéciales BR sous la forme "*truc,"
+ * @arg {string} data[writePerm] [] - Permissions spéciales BR sous la forme "*truc,"
+ * @arg {string[]} data[forlifes] [] - Liste d'alias spéciaux BR (attention le filtre .fkz n'est plus fonctionnel)
+ * @arg {string[]} data[ips] - Liste des ips connus de la personne
+ * @arg {string[]} data[groups] [] - Liste des gid dont le pax est membre (doit contenir "on_platal" si il y a lieu)
+ * @arg {string[]} data[groupsIsAdmin] [] - Liste des gid dont le pax est admin ; supposé sous-liste du précédent
+ * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
+ */
+function creerUtilisateur(user, data) {
+    return new Promise((resolve, reject) => {
+        // Calcul d'un dictionnaire d'ajout
+        let vals = {};
+
+        // uid de base généré à partir de nom et prénom, plus potentiellement promo et un offset
+        // MEF mélange de Promise et de fonction standard
+        genererUid(user, data['givenName'],data['lastName'],data['promotion']).then(id => { vals[config.key_id]=id; } );
+
+        // Ecriture de toutes les valeurs directement inscrites dans le LDAP (in pour input)
+        // Génère une erreur si un champ n'est pas rempli
+        config.user.direct_input.forEach(key_att => vals[config.user[key_att]]=data[key_att]);
+
+        // Appel à la fonction de base
+        ajouterLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_users, vals).then( res => {
+            // Modifications multiples pour avoir plusieurs champs de même type ; boucle sur les attributs multiples (d'où mul)
+            config.user.muliple_input.forEach(key_att => {
+                // On rajoute chaque valeur en entrée
+                data[key_att].forEach(val => {
+                    let vals2 = {};
+                    vals2[config.user[key_att]]=val;
+                    modifierLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_users, "add", vals2).then(res => {
+                        if (!res) { reject(false); }
+                    });
+                });
+            });
+
+            // Certains champs nécessitent de petits calculs
+            let vals3={};
+
+            // Création d'un nom complet lisible
+            vals3[config.user['fullName']]=data['givenName']+' '+data['lastName'].toUpperCase();
+            // ?!
+            vals3[config.user['password']] =  '{CRYPT}' + data['password'];
+            // Ecriture d'un surnom s'il y a lieu
+            if ((data['nickname']!=undefined)&(data['nickname']!='')) {
+                vals3[config.user['nickname']]=data['nickname'];
+            }
+            // Génération id aléatoire unique
+            genererIdNum(user, config.user['id'], config.dn_users).then(id => { vals3[config.user['id']]=id; });
+            
+            // Stockage machine ; dépend du prénom
+            vals3[config.user['directory']] = '/hosting/users/' + data['givenName'][0];
+
+            // Code root
+            vals3[config.user['cleanFullName']]=data['fullName'].replace(':', ';').toLowerCase().normalize('UFD');
+            
+            // Adressage root
+            if (data['groups'].includes("on_platal")) { vals3[config.user['login']] = "/bin/bash"; }
+            else  { vals3[config.user['login']] = "/sbin/nologin"; }
+            
+            // Permissions BR
+            vals3[config.user['readPerm']] = 'br.*,public.*';
+            if (data['readPerm'].length>0) { vals3[config.user['readPerm']] += ',' + data['readPerm']; }
+            vals3[config.user['writePerm']] = 'br.*,!br.blague-du-jour,public.*,!br.campagnekes';
+            if (data['writePerm'].length>0) { vals3[config.user['readPerm']] += ',' + data['writePerm']; }
+
+            // Valeur nécessaire mais inutile
+            vals3[config.user['idNum']] ='5000';
+
+            // Inscription des valeurs calculées
+            modifierLDAP(user, config.key_id+"="+vals[config.user['hruid']]+","+config.dn_users, "add", vals3).then(res => {
+                if (!res) { reject(false); }
+            });
+
+            ["posixAccount", "shadowAccount", "inetOrgPerson", "brAccount"].forEach(cst => {
+                let val3={};
+                vals3[config.user['class']]=cst;
+                modifierLDAP(user, config.key_id+"="+vals[config.user['hruid']]+","+config.dn_users, "add", vals3).then(res => {
+                    if (!res) { reject(false); }
+                });
+            });
+
+            // Utilisation des fonctions adaptées pour assurer la cohérence de l'ensemble
+            data['groupsIsMember'].forEach(gid => { ajouterMembreGroupe(user, vals[config.key_id], gid); });
+            data['groupsIsAdmin'].forEach(gid => { ajouterAdministrateurGroupe(user, vals[config.key_id], gid); });
+
+            resolve(true);
+        });
+        reject(false);
+    });
+}
+
+/**
+ * @summary Fonction qui créé un nouveau groupe dans le LDAP.
+ * @desc Cette fonction fait une utilisation massive d'eval pour anonymiser son code ; c'est mal et cela suppose que beaucoup de soins ont été pris lors de
+ * l'escape de ses paramètres. Appelle {@link ajouterLDAP} et {@link modifierLDAP}, mais aussi {@link ajouterMembreGroupe} et {@link ajouterAdministrateurGroupe}
+ * pour gérer les groupes du nouvel utilisateur. Attention une manip FOIREUSE est cachée dedans. 
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
  * @arg {Object} data - Dictionnaire des informations utilisateurs (voir détail des champs dans config.json)
- * @return {boolean} `true` si la modification s'est bien déroulée, false sinon
+ * @arg {string} data[name] - Nom du groupe
+ * @arg {string} data[ns] - Statut du groupe ; 'binet' ou 'free', càd ouvert à tous
+ * @arg {string[]} data[members] - Liste des membres du groupe
+ * @arg {string[]} data[admins] - Liste des admins du groupe ; supposée être une sous-liste de la précédente
+ * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
  */
-/*function creerUtilisateur(user, data) {
-    return new Promise(function(resolve, reject) {
+function creerGroupe(user, data) {
+    return new Promise((resolve, reject) => {
+        // Calcul d'un dictionnaire d'ajout
         let vals = {};
-        config.cru.single_user_infos.forEach(key => vals[key]=eval(config.cru.expr_single_values_user[key]));
-        ajouterLDAP(user, config.key_id+"="+data["uid"]+","+config.dn_users, vals).then( res => {
-            config.cru.multiple_user_infos.forEach(key => {
-                vals = {};
-                //vals[]
-                modifierLDAP(user, config.key_id+"="+data["uid"]+","+config.dn_users, ).then(res => {
-                    modifierLDAP(user, ).then(res => { resolve(true); });
+
+        // uid de base généré à partir du nom standardisé
+        genererGid(user, data['name']).then(id => { vals[config.group['name']]=id; });
+
+        // Ecriture de toutes les valeurs directement inscrites dans le LDAP (in pour input)
+        config.group.direct_input.forEach(key_att => vals[config.group[key_att]]=data[key_att]);
+
+        // Appel à la fonction de base
+        ajouterLDAP(user, config.key_id+"="+vals[config.group['name']]+","+config.dn_groups, vals).then( res => {
+            // Certains champs nécessitent de petits calculs
+            let vals2={};
+
+            // Sauvegarde du nom (pour le cas où gid != data['name'])
+            vals2[config.group["name"]]=data['name'];
+
+            // ?!
+            vals2[config.user['password']] =  '';
+
+            // Génération id aléatoire et test contre le LDAP
+            genererIdNum(user, config.groups["idNumber"], config.dn_groups).then(id => { vals2[config.group['idNumber']]=id; });
+            // FOIREUX : Hypothèse sur la structure du reste des données mais évite un assurerUnicite à deux variables
+            vals2[config.group['idNumber2']]=vals2[config.group['idNumber']];
+            
+            // Stockage machine ; dépend du prénom
+            vals2[config.group['directory']] = '/hosting/groups/'+vals[config.key_id];
+
+            // Code root
+            vals2[config.group['cleanFullName']]=data['name'].replace(':', ';').toLowerCase().normalize('UFD');
+            
+            // Adressage root
+            vals2[config.group['login']] = "/sbin/nologin";
+            
+            // Permissions BR
+            vals2[config.group['readPerm']] = '!*';
+            vals2[config.group['writePerm']] = '!*';
+
+            // Inscription des valeurs calculées
+            modifierLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_groups, "add", vals2).then(res => {
+                if (!res) { reject(false); }
+            });
+
+            ["posixAccount", "posixGroup", "brAccount"].forEach(cst => {
+                let vals3={};
+                vals3[config.group['class']]=cst;
+                modifierLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_groups, "add", vals3).then(res => {
+                    if (!res) { reject(false); }
                 });
             });
+
+            // Utilisation des fonctions adaptées pour assurer la cohérence de l'ensemble
+            data['members'].forEach(uid => { ajouterMembreGroupe(user, uid, vals[config.key_att]); });
+            data['admins'].forEach(uid => { ajouterAdministrateurGroupe(user, uid, vals[config.key_att]); });
+
+            resolve(true);
         });
         reject(false);
     });
-}*/
+}
+
+//------------------------------------------------------------------------------------------------------------------------
+// Fonctions de relation TBT
+//------------------------------------------------------------------------------------------------------------------------
+
+/**
+ * @summary Fonction qui permet de rajouter un membre déjà créé à un groupe.
+ * @desc Cette fonction fait essentiellement appel à {@link modifierLDAP} et {@link listerGroupes}. Elle n'autorise pas les doublons et opère dans les deux dns users
+ * et groups.
+ * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
+ * @arg {string} uid - Identifiant du futur membre
+ * @arg {string} gid - Identifiant du groupe
+ * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
+ */
+function ajouterMembreGroupe(user, uid, gid) {
+    return new Promise((resolve, reject) => {
+        // Vérifie que l'utilisateur est pas déjà membre pour groupes
+        listerMembres(user,gid).then(lm => {
+            if (!lm.includes(uid)) {
+                let vals = {};
+                vals[config.groups.member] = uid;
+                modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "add", vals).then(res => {
+                    // Erreur si pb lors de la modification
+                    if (!res) { reject(false); }
+                });
+            }
+        // Vérifie que l'utilisateur est pas déjà membre pour users
+        }).then(res => listerGroupes(user,uid)).then( lg => {
+            if (!lg.includes(gid)) {
+                let vals2 = {};
+                vals2[config.users.groups] = gid;
+                modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_users, { id: uid }), "add", vals2).then(res => {
+                    // Erreur si pb lors de la modification
+                    if (!res) { reject(false); }
+                });
+            }
+            resolve(true);
+        });
+    });
+}
 
 /**
- * @summary TBC Fonction qui va plonger dans le LDAP et modifier un certain jeu de valeur en argument.
- * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse 
- * puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). 
- * Il faut l'appeler suivant un schéma `modifierLDAP(...).then((res) => { truc avec res });`. Cette fonction 
- * fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat 
- * (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @summary Fonction qui permet de promouvoir membre au stade d'administrateur d'un groupe.
+ * @desc Cette fonction fait essentiellement appel à {@link ajouterMembreGroupe} {@link modifierLDAP} et {@link listerAdministrateurs}. Elle n'autorise pas
+ * les doublons et opère dans les deux dns users et groups.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
- * @arg {string} gid - Identifiant du group
- * @arg {string} nom - Nom commun du group
- * @arg {string} status - Statut du groupe (binet, autre ?)
- * @arg {string[]} admins - Admins du groupe
- * @arg {string[]} members - Nouvelle valeur des attributs
+ * @arg {string} uid - Identifiant du futur membre
+ * @arg {string} gid - Identifiant du groupe
  * @return {boolean} `true` si la modification s'est bien déroulée, false sinon
  */
-function creerGroupeLDAP(user, gid, nom, status, admins, members) {
-    return new Promise(function(resolve, reject) {
-        let data = {};
-        data["uid"] = gid;
-        data["cn"] = nom;
-        data["brNS"] = status;
-        data[""];
-        reject(false);
+function ajouterAdministrateurGroupe(user, uid, gid){
+    return new Promise((resolve, reject) => {
+        // ajouter
+        ajouterMembreGroupe(user,uid,gid).then(res => {
+            listerAdministrateurs(user,gid).includes(uid).then(la => {
+                if (!la.includes(uid)) {
+                    // Finalement modification, uniquement dans groups
+                    let vals = {};
+                    vals[config.groups.admin] = uid;
+                    modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "add", vals).then(res => {
+                        // Gestion d'erreur
+                        if (!res) { reject(false); }
+                    });
+                }
+            });
+            resolve(true);
+        });
+    });
+}
+
+/**
+ * @summary Fonction qui permet de supprimer un membre existant d'un groupe.
+ * @desc Cette fonction fait essentiellement appel à {@link rechercherLDAP}, {@link modifierLDAP}, {@link listerGroupes} et {@link listerMembres}.
+ * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
+ * @arg {string} uid - Identifiant de l'ex-membre
+ * @arg {string} gid - Identifiant du groupe
+ * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
+ */
+function supprimerMembreGroupe(user, uid, gid) {
+    return new Promise((resolve, reject) => {
+        // Vérifie que l'utilisateur est pas déjà viré pour groupes
+        listerMembres(user,gid).then(lm => {
+            if (lm.includes(uid)) {
+                // Supprime tous les utilisateurs
+                modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "del", config.group.member).then(res => {
+                    // Les rajoute un par un, sauf pour le supprimé
+                    lm.forEach(id => {
+                        if (id!=uid) { ajouterMembreGroupe(user,id, gid); }
+                    });
+                });
+            }
+        }).then(res => listerGroupes(user,uid)).then(lg => {
+            // Vérifie que l'utilisateur est pas déjà viré pour users
+            if (lg.includes(gid)) {
+                // Supprime tous les groupes
+                modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_users, { id: uid }), "del", config.group.admin).then(res => {
+                    // Les rajoute un par un, sauf pour le supprimé
+                    lg.forEach(id => {
+                        if (id!=gid) { ajouterMembreGroupe(user,uid, id); }
+                    });
+                });
+            }
+            resolve(true);
+        });
+    });
+}
+
+/**
+ * @summary Fonction qui permet de rétrograder un membre du stade d'administrateur d'un groupe au stade d'utilisateur.
+ * @desc Cette fonction fait essentiellement appel à {@link modifierLDAP}.
+ * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
+ * @arg {string} uid - Identifiant du futur membre
+ * @arg {string} gid - Identifiant du groupe
+ * @return {boolean} `true` si la modification s'est bien déroulée, false sinon
+ */
+function supprimerAdministrateurGroupe(user, uid, gid) {
+    return new Promise((resolve, reject) => {
+        // Peut paraître absurde mais permet de s'assurer que le membre est bien présent et que ses champs sont comme il faut
+        supprimerMembreGroupe(user, uid, gid).then( res => { ajouterMembreGroupe(user,uid,gid); });
+        // Vérifie que l'utilisateur est bien admins (comme dans supprimerMembreGroupe)
+        listerAdministrateurs(user,gid).then(la => {
+            if (la.includes(uid)) {
+                // Supprime tous les administrateurs
+                modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "del", config.group.admin).then(res => {
+                    // Les rajoute un par un, sauf pour le supprimé
+                    la.forEach(id => {
+                        if (id!=uid) { ajouterAdministrateurGroupe(user, id, gid); }
+                    });
+                });
+            }
+        }).then(res => resolve(true));
     });
 }
 
 //------------------------------------------------------------------------------------------------------------------------
-// Fonctions modificatrices
+// Fonctions d'édition TBT
 //------------------------------------------------------------------------------------------------------------------------
 
 /**
- * @summary TBC Fonction qui va modifier un certain jeu de valeur en argument dans le LDAP.
- * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une 
- * réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). 
- * Il faut l'appeler suivant un schéma `modifierLDAP(...).then((res) => { truc avec res });`. Cette fonction 
- * fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat 
- * (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @summary Fonction qui édite un utilisateur existant dans le LDAP. Très similaire à {@link creerUtilisateur}
+ * @desc Appelle simplement {@link creerUtilisateur} et {@link supprimerUtilisateur}, plus {@link renseignerSurUtilisateur} pour les champs non fournis.
+ * Ce choix a pour conséquence que l'ordre du dictionnaire de correspondance dans ldap_config est important.
  * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
- * @arg {string} gid - Identifiant du group
- * @arg {string} nom - Nom commun du group
- * @arg {string} status - Statut du groupe (binet, autre ?)
- * @arg {string[]} admins - Admins du groupe
- * @arg {string[]} members - Nouvelle valeur des attributs
- * @return {boolean} `true` si la modification s'est bien déroulée, false sinon
+ * @arg {string} uid - Utilisateur à modifier (le plus souvent le même, mais root possible)
+ * @arg {Object} data - Dictionnaire des informations utilisateurs au même format que pour {@link creerUtilisateur} avec tous les champs optionnels ;
+ * MEF ces valeurs vont écraser les précédentes.
+ * attention toutes les clés de cette entrée seront modifiées dans le LDAP
+ * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
+ */
+function editerUtilisateur(user, uid, data) {
+    return new Promise((resolve, reject) => {
+        // Récupération des anciennes données
+        renseignerSurUtilisateur(user, uid).then(profil => {
+            // Reecriture de profil avec les bons champs
+            Object.keys(profil).forEach(keyLDAP => {
+                Object.keys(config.user).forEach(keyAlias => {
+                    config.user[keyAlias]=keyLDAP;
+                    profil[keyAlias]=profil[keyLDAP];
+                });
+            });
+            // Régénération du champ manquant dans profil
+            listerGroupes(user, uid).then(lg => {
+                profil['groupsIsAdmin']=[];
+                lg.forEach(gid =>{
+                    listerAdministrateurs(gid).then(la =>{
+                        if (la.includes(uid)) { profil['groupsIsAdmin'].push(gid); }
+                    }).then(res => {
+                        // Surcharge des champs à modifier selon data
+                        Object.keys(data).forEach(key => {
+                            profil[key]=data[key];
+                        });
+                        // Modification propre
+                        supprimerUtilisateur(user, uid).then(r => {
+                            creerUtilisateur(user, profil).then(res => { if (!res) {reject(false); }});
+                        }).then (res => { resolve(true); });
+                    });
+                });
+            });
+        });
+    });
+}
+
+/**
+ * @summary Fonction qui édite un groupe existant dans le LDAP. Très similaire à {@link creerGroupe}
+ * @desc Appelle {@link ajouterLDAP} bien sûr, mais aussi {@link ajouterMembreGroupe} et {@link ajouterAdministrateurGroupe} pour gérer les groupes du nouvel utilisateur.
+ * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
+ * @arg {string} gid - Identifiant du groupe à modifier
+ * @arg {Object} data - Dictionnaire des informations utilisateurs au même format que pour {@link creerGroupe} avec tous les champs optionnels.
+ * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
+ */
+function editerGroupe(user, gid, data) {
+    return new Promise((resolve, reject) => {
+        // Récupération des anciennes données
+        renseignerSurGroupe(user, gid).then(profil => {
+            // Reecriture de profil avec les bons champs
+            Object.keys(profil).forEach(keyLDAP => {
+                Object.keys(config.group).forEach(keyAlias => {
+                    config.group[keyAlias]=keyLDAP;
+                    profil[keyAlias]=profil[keyLDAP];
+                });
+            });
+            // Surcharge des champs à modifier selon data
+            Object.keys(data).forEach(key => {
+                profil[key]=data[key];
+            });
+            // Modification propre
+            supprimerGroupe(user, gid).then(r => {
+                creerGroupe(user, profil).then(res => { if (!res) { reject(false); }});
+            }).then(res => { resolve(true); });
+        });
+    });
+}
+
+//------------------------------------------------------------------------------------------------------------------------
+// Fonctions de suppression TBT
+//------------------------------------------------------------------------------------------------------------------------
+
+/**
+ * @summary Fonction qui supprime un utilisateur du LDAP.
+ * @desc Cette fonction commence par gérer les groupes du membre puis le supprime entièrement.
+ * Appelle {@link supprimerLDAP} bien sûr, mais aussi {@link supprimerMembreGroupe} et {@link supprimerAdministrateurGroupe} pour gérer les groupes de l'utilisateur sortant.
+ * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
+ * @arg {string} uid - uid de la victime
+ * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
+ */
+function supprimerUtilisateur(user, uid) {
+    return new Promise((resolve, reject) => {
+        // Gestion des groupes d'abord
+        renseignerSurUtilisateur(user, uid).then(profil => {
+            profil[config.user['groups']].forEach(gid => {
+                listerAdministrateurs(user, gid).then(la => {
+                    if (la.includes(uid)) { supprimerAdministrateurGroupe(user, uid, gid); }
+                }).then(res => { supprimerMembreGroupe(user, uid, gid); });
+            });
+        // Elimination
+        }).then(res => { supprimerLDAP(user, config.key_id+"="+uid+","+config.dn_users); });
+    });
+}
+
+/**
+ * @summary Fonction qui supprime un groupe du LDAP.
+ * @desc Cette fonction commence par gérer les groupes du membre puis le supprime entièrement.
+ * Appelle {@link supprimerLDAP} bien sûr, mais aussi {@link supprimerMembreGroupe} et {@link supprimerAdministrateurGroupe} pour gérer les groupes de l'utilisateur sortant.
+ * @arg {Object} user - Utilisateur de la forme nécessaire à {@link connecterLDAP}
+ * @arg {string} gid - gid de la victime
+ * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
  */
-function rajouterLDAP(user, gid, nom, status, admins, members) {
+function supprimerGroupe(user, gid) {
     return new Promise(function(resolve, reject) {
-        let data = {};
-        data["uid"] = gid;
-        data["cn"] = nom;
-        data["brNS"] = status;
-        data[""];
-        reject(false);
+        // Gestion des membres et administrateurs d'abord
+        renseignerSurGroupe(user, gid).then(profil => {
+            profil[config.group['admin']].forEach(id => { supprimerAdministrateurGroupe(user, id, gid); });
+            profil[config.group['member']].forEach(id => { supprimerMembreGroupe(user, id, gid); });
+        // Elimination
+        }).then(res => {
+            supprimerLDAP(user, config.key_id+"="+gid+","+config.dn_groups);
+        }).then(res => { if (res) {resolve(true); }});
     });
 }
 
-//listerGroupes({},"anatole.romon").then(res => console.log(res));
-//listerMembres({},"bda").then(res => console.log(res));
-//listerAdministrateurs({},"kes").then(res => console.log(res));
-//renseignerSurUtilisateur({},"wilson.jallet").then(res => console.log(res));
-//trouverGroupes({},"ensta").then(res => console.log(res));
-//repliquerTOLdesIds({},{"groups": ["faerix","br"]}).then(res => console.log(res));
-//repliquerTOL({},{"groups": ["faerix","br"]}).then(res => console.log(res));
-//rechercherLDAP({},"ou=groups,dc=frankiz,dc=net","(cn=f*)",["uid"]).then(res => console.log(res));
-//listeAdmins({},"zqfnsflswndf").then(res => console.log(res));
 //trouverGroupesParTypes({},"fe","binet").then(res => console.log(res));
 
 /* Partage pour le reste du monde ; même remarque synthaxe que pour l'import
diff --git a/src/server.js b/src/server.js
index 291e78e0301e8827ee7051bf3644f55ced3da86b..af64a856f58d649243d5718806047a07a6b4e248 100644
--- a/src/server.js
+++ b/src/server.js
@@ -10,6 +10,7 @@ import schema from './graphql/schema';
 import { express as graphqlVoyager } from 'graphql-voyager/middleware';
 import { graphqlExpress, graphiqlExpress } from 'graphql-server-express';
 import flash from 'connect-flash';
+import { ensureLoggedIn } from 'connect-ensure-login';
 import passport from 'passport';
 import LdapStrategy from 'passport-ldapauth';
 import fs from 'fs';
@@ -21,7 +22,6 @@ import path from 'path';
 import cors from 'cors';
 
 const server = express();
-
 // on sait pas a quoi ca sert mais il parait que c'est utile
 server.use(bodyParser.json());
 server.use(bodyParser.urlencoded({
@@ -113,7 +113,7 @@ server.use('/graphql', bodyParser.json(),
     }));
 
 // GraphiQL est une console interactive pour faire des requêtes au schéma GraphQL
-server.use('/graphiql', graphiqlExpress({endpointURL: '/graphql'}));
+server.use('/graphiql', /*ensureLoggedIn('/login'),*/ graphiqlExpress({endpointURL: '/graphql'}));
 
 // GraphQL voyager
 server.use('/voyager', graphqlVoyager({ endpointUrl: '/graphql' }));
diff --git a/webpack.config.js b/webpack.config.js
index 192a23d259b42d65fd9ccf028e7e989052844c8c..0d258d9676c3fae2436511bcfe6f3c55d45e4695 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,5 +1,6 @@
 const path = require('path');
 const nodeExternals = require('webpack-node-externals');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
 
 const config = {
     entry: './src/index.js',
@@ -8,14 +9,19 @@ const config = {
     
     output: {
         path: path.resolve(__dirname, 'build'),
-        publicPath: '/',
+        publicPath: '/assets/',
         filename: 'bundle.js'
     },
     
     externals: [nodeExternals()],
     
     module: {
-        loaders: [{
+
+        rules: [{
+            test: /\.js$/,
+            exclude: /node_modules/,
+            use: [ 'eslint-loader' ]
+        },{
             test: /\.css$/,
             use: ['style-loader', 'css-loader']
         },{
@@ -26,7 +32,21 @@ const config = {
                 limit: 10000
             }
         }]
-    }
+    },
+
+    plugins: [
+        new CopyWebpackPlugin([{
+            from: 'src/css',
+            to: 'css'
+        },{
+            from: 'src/views',
+            to: 'views'
+        },{
+            from: 'package.json',
+            to: 'package.json'
+        }]
+        )
+    ]
 };
 
 module.exports = config;
\ No newline at end of file