migrate to redux-offline + various optimisation
authorymh <ymh.work@gmail.com>
Tue, 20 Jun 2017 14:13:15 +0200
changeset 62 b2514a9bcd49
parent 61 7586b4a11c32
child 63 4088f8dc6b52
migrate to redux-offline + various optimisation
client/package.json
client/src/APIClient.js
client/src/actions/notesActions.js
client/src/actions/sessionsActions.js
client/src/api/APIClient.js
client/src/api/index.js
client/src/components/Login.js
client/src/components/Navbar.js
client/src/components/NotesList.js
client/src/components/Session.js
client/src/components/SessionList.js
client/src/components/Sessions.js
client/src/components/SlateEditor.js
client/src/index.js
client/src/reducers/authReducer.js
client/src/reducers/index.js
client/src/reducers/notesReducer.js
client/src/reducers/sessionsReducer.js
client/src/sagas/index.js
client/src/store/configureStore.js
client/src/store/noteRecord.js
client/src/store/sessionRecord.js
client/yarn.lock
--- a/client/package.json	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/package.json	Tue Jun 20 14:13:15 2017 +0200
@@ -6,10 +6,9 @@
   "dependencies": {
     "bootstrap-sass": "^3.3.7",
     "immutable": "^3.8.1",
+    "localforage": "^1.5.0",
     "lodash": "^4.17.4",
     "moment": "^2.18.1",
-    "pouchdb": "^6.2.0",
-    "pouchdb-find": "^6.2.0",
     "react": "^15.5.4",
     "react-bootstrap": "^0.31.0",
     "react-dom": "^15.5.4",
@@ -17,8 +16,9 @@
     "react-redux": "^5.0.5",
     "react-router-redux": "next",
     "redux": "^3.6.0",
-    "redux-history-transitions": "^2.2.0",
     "redux-immutable": "^4.0.0",
+    "redux-offline": "^2.0.0",
+    "redux-persist-transform-immutable": "^4.3.0",
     "redux-saga": "^0.15.3",
     "slate": "^0.20.1",
     "uuid": "^3.0.1"
--- a/client/src/APIClient.js	Tue Jun 20 12:11:57 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-class APIClient {
-  constructor(baseURL, store) {
-    this.baseURL = baseURL;
-    this.store = store;
-  }
-
-  createRequest = (method, uri, data, headers) => {
-
-    headers = headers || new Headers();
-    headers.append("Content-Type", "application/json");
-
-    var options = {
-      method: method,
-      headers: headers,
-    };
-
-    if (data) {
-      options.body = JSON.stringify(data);
-    }
-
-    // TODO : use URL-module to build URL
-    return new Request(this.baseURL + uri, options);
-  }
-
-  getToken = () => {
-    const state = this.store.getState();
-    return state.get('token');
-  }
-
-  hasToken = () => {
-    //const token = localStorage.getItem('token');
-    const token = this.getToken();
-
-    return token !== null;
-  }
-
-  createAuthorizedRequest = (method, uri, data) => {
-
-    var headers = new Headers(),
-        //token = localStorage.getItem('token') || '';
-        token = this.getToken() || '';
-    headers.append("Authorization", "JWT " + token);
-
-    return this.createRequest(method, uri, data, headers);
-  }
-
-  request = (method, uri, data) => {
-    console.log(method + ' ' + uri);
-    var req = this.hasToken() ? this.createAuthorizedRequest(method, uri, data) : this.createRequest(method, uri, data);
-    return this.fetch(req, { credentials: 'include' });
-  }
-
-  get = (uri, data) => {
-    return this.request('GET', uri, data);
-  }
-
-  post = (uri, data) => {
-    return this.request('POST', uri, data);
-  }
-
-  put = (uri, data) => {
-    return this.request('PUT', uri, data);
-  }
-
-  fetch = (req) => {
-    return new Promise((resolve, reject) => {
-      fetch(req)
-        .then((response) => {
-          if (response.ok) {
-            return response.json().then((data) => resolve(data));
-          } else {
-            return response.json().then((data) => reject(data));
-          }
-        });
-    });
-  }
-}
-
-export default APIClient
--- a/client/src/actions/notesActions.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/actions/notesActions.js	Tue Jun 20 14:13:15 2017 +0200
@@ -4,7 +4,7 @@
 
 export const addNote = (session, data) => {
   return {
-    type: types.ADD_NOTE_ASYNC,
+    type: types.ADD_NOTE,
     note: {
       _id: uuidV1(),
       session: session._id,
@@ -20,7 +20,7 @@
 
 export const loadNotesBySession = (session) => {
   return {
-    type: types.LOAD_NOTES_BY_SESSION_ASYNC,
+    type: types.LOAD_NOTES_BY_SESSION,
     session: session
   }
 }
--- a/client/src/actions/sessionsActions.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/actions/sessionsActions.js	Tue Jun 20 14:13:15 2017 +0200
@@ -1,22 +1,38 @@
-import uuidV1 from 'uuid/v1';
+//import uuidV1 from 'uuid/v1';
 
 import * as types from '../constants/actionTypes';
 
-export const createSession = () => {
-  return {
-    type: types.CREATE_SESSION_ASYNC,
-    session: {
-      _id: uuidV1(),
+export const createSession = (sessionId) => {
+
+  //const sessionId = uuidV1();
+  const newSession = {
+      _id: sessionId,
+      ext_id: sessionId,
       date: new Date(),
       title: '',
       description: '',
+  };
+
+  return {
+    type: types.CREATE_SESSION,
+    session: newSession,
+    meta: {
+      offline: {
+        effect: {
+          url: "/api/notes/sessions/",
+          method: 'POST',
+          data: newSession
+        },
+        commit: { type: types.CREATE_SESSION_ASYNC },
+        rollback: { type: 'NoOp'}
+      }
     }
   };
 }
 
 export const updateSession = (session, values) => {
   return {
-    type: types.UPDATE_SESSION_ASYNC,
+    type: types.UPDATE_SESSION,
     session: session,
     values: values,
   };
@@ -24,6 +40,6 @@
 
 export const loadSessions = () => {
   return {
-    type: types.LOAD_SESSIONS_ASYNC
+    type: types.LOAD_SESSIONS
   }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/api/APIClient.js	Tue Jun 20 14:13:15 2017 +0200
@@ -0,0 +1,80 @@
+class APIClient {
+  constructor(baseURL) {
+    this.baseURL = baseURL;
+  }
+
+  setStore = (store) => {
+    this.store = store;
+  }
+
+  createRequest = (method, uri, data, headers) => {
+
+    headers = headers || new Headers();
+    headers.append("Content-Type", "application/json");
+
+    var options = {
+      method: method,
+      headers: headers,
+    };
+
+    if (data) {
+      options.body = JSON.stringify(data);
+    }
+
+    // TODO : use URL-module to build URL
+    return new Request(this.baseURL + uri, options);
+  }
+
+  getToken = () => {
+    const state = this.store.getState();
+    return state['token'];
+  }
+
+  hasToken = () => {
+    const token = this.getToken();
+
+    return token !== null && token !== '';
+  }
+
+  createAuthorizedRequest = (method, uri, data) => {
+
+    var headers = new Headers(),
+        token = this.getToken() || '';
+    headers.append("Authorization", "JWT " + token);
+
+    return this.createRequest(method, uri, data, headers);
+  }
+
+  request = (method, uri, data) => {
+    console.log(method + ' ' + uri);
+    var req = this.hasToken() ? this.createAuthorizedRequest(method, uri, data) : this.createRequest(method, uri, data);
+    return this.fetch(req, { credentials: 'include' });
+  }
+
+  get = (uri, data) => {
+    return this.request('GET', uri, data);
+  }
+
+  post = (uri, data) => {
+    return this.request('POST', uri, data);
+  }
+
+  put = (uri, data) => {
+    return this.request('PUT', uri, data);
+  }
+
+  fetch = (req) => {
+    return new Promise((resolve, reject) => {
+      fetch(req)
+        .then((response) => {
+          if (response.ok) {
+            return response.json().then((data) => resolve(data));
+          } else {
+            return response.json().then((data) => reject(data));
+          }
+        });
+    });
+  }
+}
+
+export default APIClient
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/api/index.js	Tue Jun 20 14:13:15 2017 +0200
@@ -0,0 +1,6 @@
+
+export default apiClient => (effect, action) => {
+
+  const { method, url, data } = effect;
+  return apiClient.request(method, url, data);
+}
--- a/client/src/components/Login.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/components/Login.js	Tue Jun 20 14:13:15 2017 +0200
@@ -52,8 +52,8 @@
 
 function mapStateToProps(state, props) {
   return {
-    currentUser: state.get('currentUser'),
-    login: state.get('login')
+    currentUser: state['currentUser'],
+    login: state['login']
   };
 }
 
--- a/client/src/components/Navbar.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/components/Navbar.js	Tue Jun 20 14:13:15 2017 +0200
@@ -1,4 +1,3 @@
-
 import PropTypes from 'prop-types';
 import React, { Component } from 'react';
 import { connect } from 'react-redux';
@@ -36,9 +35,9 @@
 
   renderLogin() {
 
-    if (this.props.currentUser) {
+    if (this.props.isAuthenticated) {
       return (
-        <NavDropdown title={ this.props.currentUser.username } id="user-dropdown">
+        <NavDropdown title={ this.props.currentUser.get('username') } id="user-dropdown">
           <MenuItem onClick={this.onClickSettings}>Settings</MenuItem>
           <MenuItem onClick={this.onClickLogout}>Logout</MenuItem>
         </NavDropdown>
@@ -78,8 +77,8 @@
 
 function mapStateToProps(state, props) {
   return {
-    isAuthenticated: state.get('isAuthenticated'),
-    currentUser: state.get('currentUser'),
+    isAuthenticated: state['isAuthenticated'],
+    currentUser: state['currentUser'],
   };
 }
 
--- a/client/src/components/NotesList.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/components/NotesList.js	Tue Jun 20 14:13:15 2017 +0200
@@ -14,7 +14,6 @@
       <Alert bsStyle="warning">No notes yet. Add notes with the textarea below.</Alert>
     );
   }
-
   return (
     <div>
       {notes.map((note) =>
--- a/client/src/components/Session.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/components/Session.js	Tue Jun 20 14:13:15 2017 +0200
@@ -12,10 +12,6 @@
 
 class Session extends Component {
 
-  componentDidMount = () => {
-    this.props.notesActions.loadNotesBySession({ _id: this.props.match.params.id });
-  }
-
   render() {
     return (
       <div>
@@ -50,14 +46,18 @@
 
   const sessionId = props.match.params.id;
 
-  const sessions = state.get('sessions');
-  const notes = state.get('notes');
+  const sessions = state['sessions'];
+  const notes = state['notes'];
+
   const currentSession = sessions.find(session => session._id === sessionId);
+  const currentNotes = notes.filter(note => {
+        return note.session === sessionId;
+    });
 
   return {
     currentSession,
     sessions,
-    notes,
+    notes: currentNotes,
   };
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/components/SessionList.js	Tue Jun 20 14:13:15 2017 +0200
@@ -0,0 +1,58 @@
+import React, { Component } from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import { Grid, Row, Col, ListGroup, ListGroupItem, Button } from 'react-bootstrap';
+import moment from 'moment';
+import '../App.css';
+import Navbar from './Navbar';
+import * as sessionsActions from '../actions/sessionsActions';
+import uuidV1 from 'uuid/v1';
+
+class SessionList extends Component {
+
+  createSession = () => {
+    const sessionId = uuidV1();
+    this.props.sessionsActions.createSession(sessionId);
+    this.props.history.push('/sessions/' + sessionId);
+  }
+
+  render() {
+    return (
+      <div>
+        <Navbar history={this.props.history} />
+        <Grid fluid>
+          <Row>
+            <Col md={6} mdOffset={3}>
+              <ListGroup>
+                {this.props.sessions.map((session) =>
+                  <ListGroupItem
+                    key={session.get('_id')}
+                    onClick={() => this.props.history.push('/sessions/' + session.get('_id'))}>
+                    {session.title || 'No title'} {session.get('_id')} {moment(session.get('date')).format('DD/MM/YYYY')}
+                  </ListGroupItem>
+                )}
+              </ListGroup>
+              <Button bsStyle="success" onClick={this.createSession}>Create new session</Button>
+            </Col>
+          </Row>
+        </Grid>
+      </div>
+    );
+  }
+}
+
+function mapStateToProps(state, props) {
+  return {
+    // currentSession: state.get('currentSession'),
+    // sessions: state.get('sessions')
+    sessions: state['sessions']
+  };
+}
+
+function mapDispatchToProps(dispatch) {
+  return {
+    sessionsActions: bindActionCreators(sessionsActions, dispatch)
+  }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(SessionList);
--- a/client/src/components/Sessions.js	Tue Jun 20 12:11:57 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { bindActionCreators } from 'redux';
-import { Grid, Row, Col, ListGroup, ListGroupItem, Button } from 'react-bootstrap';
-import moment from 'moment';
-import '../App.css';
-import Navbar from './Navbar';
-import * as sessionsActions from '../actions/sessionsActions';
-
-class Sessions extends Component {
-
-  createSession = () => {
-    this.props.sessionsActions.createSession();
-  }
-
-  componentDidUpdate = () => {
-    if (this.props.currentSession) {
-      this.props.history.push('/sessions/' + this.props.currentSession._id)
-    }
-  }
-
-  render() {
-    return (
-      <div>
-        <Navbar history={this.props.history} />
-        <Grid fluid>
-          <Row>
-            <Col md={6} mdOffset={3}>
-              <ListGroup>
-                {this.props.sessions.map((session) =>
-                  <ListGroupItem
-                    key={session._id}
-                    onClick={() => this.props.history.push('/sessions/' + session._id)}>
-                    {session.title || 'No title'} {session._id} {moment(session.date).format('DD/MM/YYYY')}
-                  </ListGroupItem>
-                )}
-              </ListGroup>
-              <Button bsStyle="success" onClick={this.createSession}>Create new session</Button>
-            </Col>
-          </Row>
-        </Grid>
-      </div>
-    );
-  }
-}
-
-function mapStateToProps(state, props) {
-  return {
-    currentSession: state.get('currentSession'),
-    sessions: state.get('sessions')
-  };
-}
-
-function mapDispatchToProps(dispatch) {
-  return {
-    sessionsActions: bindActionCreators(sessionsActions, dispatch)
-  }
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(Sessions);
--- a/client/src/components/SlateEditor.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/components/SlateEditor.js	Tue Jun 20 14:13:15 2017 +0200
@@ -480,7 +480,7 @@
 
   updateMenu = () => {
 
-    const { hoveringMenu, state } = this.state
+    const { hoveringMenu } = this.state
 
     if (!hoveringMenu) return
 
--- a/client/src/index.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/index.js	Tue Jun 20 14:13:15 2017 +0200
@@ -6,7 +6,7 @@
 import createHistory from 'history/createBrowserHistory';
 
 import App from './App';
-import Sessions from './components/Sessions';
+import SessionList from './components/SessionList';
 import Session from './components/Session';
 import Login from './components/Login';
 import Settings from './components/Settings';
@@ -26,7 +26,7 @@
       <div>
         <Route exact path="/settings" component={Settings} />
         <Route exact path="/sessions/:id" component={Session} />
-        <Route exact path="/sessions" component={Sessions} />
+        <Route exact path="/sessions" component={SessionList} />
         <Route exact path="/login" component={Login} />
         <Route exact path="/" component={App} />
       </div>
--- a/client/src/reducers/authReducer.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/reducers/authReducer.js	Tue Jun 20 14:13:15 2017 +0200
@@ -1,7 +1,12 @@
+import Immutable from 'immutable';
 import * as types from '../constants/actionTypes';
 
 export const isAuthenticated = (state = false, action) => {
   switch (action.type) {
+    case types.AUTH_LOGOUT:
+      return false;
+    case types.AUTH_LOGIN_SUCCESS:
+      return true;
     default:
       return state;
   }
@@ -10,15 +15,14 @@
 export const currentUser = (state = null, action) => {
   switch (action.type) {
     case types.AUTH_LOGOUT:
-      localStorage.removeItem('currentUser');
       return null;
     case types.AUTH_LOGIN_SUCCESS:
-      return action.user;
+      return Immutable.Map(action.user);
     case types.USER_UPDATE_SETTINGS:
-      state.first_name = action.firstname;
-      state.last_name = action.lastname;
-      localStorage.setItem('currentUser', JSON.stringify(state));
-      return state;
+      return state.merge({
+        first_name: action.firstname,
+        last_name: action.lastname
+      });
     default:
       return state;
   }
@@ -27,7 +31,6 @@
 export const token = (state = null, action) => {
   switch (action.type) {
     case types.AUTH_LOGOUT:
-      localStorage.removeItem('token');
       return null;
     case types.AUTH_STORE_TOKEN:
       return action.token;
@@ -36,28 +39,27 @@
   }
 }
 
-// TODO Use Immutable.Map
-const loginState = {
+const loginState = Immutable.Map({
   loading: false,
   success: false,
   error: false,
-}
+});
 
 export const login = (state = loginState, action) => {
   switch (action.type) {
     case types.AUTH_LOGIN_REQUEST:
-      return {
+      return Immutable.Map({
         loading: true,
         success: false,
         error: false,
-      }
+      })
     case types.AUTH_LOGIN_SUCCESS:
     case types.AUTH_LOGIN_ERROR:
-      return {
+      return Immutable.Map({
         loading: false,
         success: action.type === types.AUTH_LOGIN_SUCCESS,
         error: action.type === types.AUTH_LOGIN_ERROR,
-      }
+      })
     default:
       return state
   }
--- a/client/src/reducers/index.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/reducers/index.js	Tue Jun 20 14:13:15 2017 +0200
@@ -1,12 +1,12 @@
-import { combineReducers } from 'redux-immutable';
+//import { combineReducers } from 'redux-immutable';
+import { combineReducers } from 'redux';
 import { routerReducer } from 'react-router-redux';
 
 import notes from './notesReducer';
-import { currentSession, sessions } from './sessionsReducer';
+import { sessions } from './sessionsReducer';
 import { isAuthenticated, currentUser, login, token } from './authReducer';
 
 const rootReducer = combineReducers({
-  currentSession,
   sessions,
   notes,
   isAuthenticated,
--- a/client/src/reducers/notesReducer.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/reducers/notesReducer.js	Tue Jun 20 14:13:15 2017 +0200
@@ -1,13 +1,14 @@
 import Immutable from 'immutable';
 import * as types from '../constants/actionTypes';
-import noteRecord from '../store/noteRecord';
+import NoteRecord from '../store/noteRecord';
 
 export default (state = Immutable.List([]), action) => {
   switch (action.type) {
     case types.ADD_NOTE:
-      return state.push(new noteRecord(action.note));
+      return state.push(new NoteRecord(action.note));
     case types.LOAD_NOTES_BY_SESSION:
-      return action.notes;
+      //return action.notes;
+      return state;
     default:
       return state;
   }
--- a/client/src/reducers/sessionsReducer.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/reducers/sessionsReducer.js	Tue Jun 20 14:13:15 2017 +0200
@@ -1,26 +1,27 @@
 import Immutable from 'immutable';
 import * as types from '../constants/actionTypes';
+import SessionRecord from '../store/sessionRecord';
 
-export const currentSession = (state = null, action) => {
-  switch (action.type) {
-    case types.CREATE_SESSION:
-      return action.session;
-    default:
-      return state;
-  }
-};
+// export const currentSession = (state = null, action) => {
+//   switch (action.type) {
+//     case types.CREATE_SESSION:
+//       return action.session;
+//     default:
+//       return state;
+//   }
+// };
 
 export const sessions = (state = Immutable.List([]), action) => {
   switch (action.type) {
     case types.CREATE_SESSION:
-      return state.push(action.session);
+      return state.push(new SessionRecord(action.session));
     case types.UPDATE_SESSION:
       const sessionToUpdate = state.find(session => session === action.session);
       const sessionIndex = state.indexOf(action.session);
       if (sessionIndex === -1) {
         return state;
       }
-      const updatedSession = Object.assign({}, sessionToUpdate, action.values);
+      const updatedSession = sessionToUpdate.merge(action.values);
       return state.set(sessionIndex, updatedSession);
     case types.LOAD_SESSIONS:
       return action.sessions;
--- a/client/src/sagas/index.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/sagas/index.js	Tue Jun 20 14:13:15 2017 +0200
@@ -1,90 +1,5 @@
-import PouchDB from 'pouchdb'
-import { put, take, takeLatest, all } from 'redux-saga/effects'
+import { put, take, all } from 'redux-saga/effects'
 import * as types from '../constants/actionTypes';
-import PouchDBFind from 'pouchdb-find';
-import Immutable from 'immutable';
-
-PouchDB.debug.disable();
-PouchDB.plugin(PouchDBFind);
-
-const sessionsDB = new PouchDB('sessions');
-const notesDB = new PouchDB('notes');
-notesDB.createIndex({
-  index: { fields: ['session'] }
-});
-
-// ---
-
-export function* loadSessions() {
-  const response = yield sessionsDB.allDocs({ include_docs: true })
-  const sessions = response.rows.map(row => row.doc)
-  yield put({ type: types.LOAD_SESSIONS, sessions: Immutable.List(sessions) })
-}
-
-export function* watchLoadSessions() {
-  yield takeLatest(types.LOAD_SESSIONS_ASYNC, loadSessions)
-}
-
-// ---
-
-export function* createSession(action) {
-  const response = yield sessionsDB.put(action.session);
-  // TODO Error control
-  const session = Object.assign({}, action.session, { rev: response.rev });
-  yield put({ type: types.CREATE_SESSION, session: session })
-}
-
-export function* watchCreateSession() {
-  yield takeLatest(types.CREATE_SESSION_ASYNC, createSession)
-}
-
-// ---
-
-export function* updateSession(action) {
-
-  const { _id } = action.session;
-  let session;
-
-  const doc = yield sessionsDB.get(_id);
-  session = Object.assign({}, doc, action.values);
-  const response = yield sessionsDB.put(session);
-
-  yield put({
-    type: types.UPDATE_SESSION,
-    session: Object.assign({}, session, { rev: response.rev })
-  })
-}
-
-export function* watchUpdateSession() {
-  yield takeLatest(types.UPDATE_SESSION_ASYNC, updateSession)
-}
-
-// ---
-
-export function* addNote(action) {
-  const response = yield notesDB.put(action.note);
-  // TODO Error control
-  const note = Object.assign({}, action.note, { rev: response.rev });
-  yield put({ type: types.ADD_NOTE, note: note })
-}
-
-export function* watchAddNote() {
-  yield takeLatest(types.ADD_NOTE_ASYNC, addNote)
-}
-
-// ---
-
-export function* loadNotesBySession(action) {
-  const result = yield notesDB.find({
-    selector: { session: action.session._id },
-    // sort: ['name']
-  });
-  yield put({ type: types.LOAD_NOTES_BY_SESSION, notes: Immutable.List(result.docs) })
-}
-
-export function* watchLoadNotesBySession() {
-  yield takeLatest(types.LOAD_NOTES_BY_SESSION_ASYNC, loadNotesBySession)
-}
 
 // ---
 
@@ -103,24 +18,22 @@
         const client = context.client;
         const response = yield client.post('/api/auth/login/', { username, password });
 
-        localStorage.setItem('currentUser', JSON.stringify(response.user));
-        localStorage.setItem('token', response.token);
-
         const actions = [{
           type: types.AUTH_LOGIN_SUCCESS,
           user: response.user,
           token: response.token,
-          meta: {
-            transition: (prevState, nextState, action) => ({
-              pathname: '/sessions',
-            }),
-          },
+        //   meta: {
+        //     transition: (prevState, nextState, action) => ({
+        //       pathname: '/sessions',
+        //     }),
+        //   },
         }, {
           type: types.AUTH_STORE_TOKEN_ASYNC,
           token: response.token,
         }];
 
-        yield all(actions.map(action => put(action)))
+        yield all(actions.map(action => put(action)));
+        context.history.push('/sessions');
 
     } catch(e) {
         yield put({ type: types.AUTH_LOGIN_ERROR, error: e });
@@ -156,11 +69,6 @@
 
 export default function* rootSaga(context) {
   yield all([
-    watchLoadSessions(),
-    watchLoadNotesBySession(),
-    watchAddNote(),
-    watchCreateSession(),
-    watchUpdateSession(),
     watchLoginSubmit(),
     watchLoginRequest(context),
     watchStoreToken(),
--- a/client/src/store/configureStore.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/store/configureStore.js	Tue Jun 20 14:13:15 2017 +0200
@@ -1,51 +1,79 @@
 import rootReducer from '../reducers';
 import rootSaga from '../sagas';
-import { loadSessions } from '../actions/sessionsActions';
-import { createStore, applyMiddleware, compose } from 'redux';
+import { compose, createStore, applyMiddleware } from 'redux';
 import { routerMiddleware } from 'react-router-redux';
-import handleTransitions from 'redux-history-transitions';
 import createSagaMiddleware from 'redux-saga'
 import Immutable from 'immutable';
-import APIClient from '../APIClient';
+import { offline } from 'redux-offline';
+import offlineDefaultConfig from 'redux-offline/lib/defaults';
+import localForage from 'localforage';
+import immutableTransform from 'redux-persist-transform-immutable'
+import NoteRecord from './noteRecord'
+import SessionRecord from './sessionRecord'
+import APIClient from '../api/APIClient';
+import createEffect from '../api';
 import config from '../config';
 
-const token = localStorage.getItem('token');
-const currentUser = localStorage.getItem('currentUser');
+// const composeEnhancers = (process.env.NODE_ENV !== 'production' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ?
+//     window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
+//         shouldHotReload: false,
+//     }) : compose;
+const composeEnhancers = compose;
+
 
 const defaultState = {
-  currentSession: null,
   sessions: Immutable.List([]),
   notes: Immutable.List([]),
-  isAuthenticated: token !== null,
-  currentUser: currentUser ? JSON.parse(currentUser) : null,
-  token: token,
-  login: {
+  isAuthenticated: false,
+  currentUser: null,
+  token: '',
+  login: Immutable.Map({
     loading: false,
     success: false,
     error: false,
-  }
+  })
 };
 
-const storeInitialState = Immutable.Map(defaultState);
+const immutableTransformConfig = {
+  records: [NoteRecord, SessionRecord],
+  whitelist: ['sessions', 'notes', 'currentUser']
+}
+
+const persistOptions = {
+  storage: localForage,
+  transforms: [immutableTransform(immutableTransformConfig)],
+  whitelist: ['sessions', 'notes', 'isAuthenticated', 'currentUser', 'token']
+}
+
+const apiClient = new APIClient(config.apiRootUrl);
+
+const offlineConfig = {
+  ...offlineDefaultConfig,
+  persistOptions,
+  effect: createEffect(apiClient)
+//  detectNetwork: callback => callback(true),
+}
+
+const storeInitialState = { ...defaultState };
+
 
 export default (history, initialState = storeInitialState) => {
 
   const router = routerMiddleware(history);
   const saga = createSagaMiddleware();
-  const transitions = handleTransitions(history);
 
-  const store = createStore(rootReducer, initialState, compose(
-    applyMiddleware(router, saga),
-    transitions
+  const store = offline(offlineConfig)(createStore)(rootReducer, initialState, composeEnhancers(
+    applyMiddleware(router, saga)
   ));
 
+  apiClient.setStore(store);
+
   const context = {
-      client: new APIClient(config.apiRootUrl, store)
+    client: apiClient,
+    history
   }
 
   saga.run(rootSaga, context);
 
-  store.dispatch(loadSessions());
-
   return store;
 };
--- a/client/src/store/noteRecord.js	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/src/store/noteRecord.js	Tue Jun 20 14:13:15 2017 +0200
@@ -12,4 +12,4 @@
   finishedAt: '',
 
   categories: []
-});
+}, 'Note');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/store/sessionRecord.js	Tue Jun 20 14:13:15 2017 +0200
@@ -0,0 +1,11 @@
+import Immutable from 'immutable';
+
+export default Immutable.Record({
+  _id: '',
+
+  title: '',
+  description: '',
+
+  date: '',
+
+}, 'Session');
--- a/client/yarn.lock	Tue Jun 20 12:11:57 2017 +0200
+++ b/client/yarn.lock	Tue Jun 20 14:13:15 2017 +0200
@@ -17,18 +17,6 @@
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"
 
-abstract-leveldown@~2.4.0:
-  version "2.4.1"
-  resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.4.1.tgz#b3bfedb884eb693a12775f0c55e9f0a420ccee64"
-  dependencies:
-    xtend "~4.0.0"
-
-abstract-leveldown@~2.6.1:
-  version "2.6.1"
-  resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.1.tgz#f9014a5669b746418e145168dea49a044ae15900"
-  dependencies:
-    xtend "~4.0.0"
-
 accepts@~1.3.3:
   version "1.3.3"
   resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
@@ -54,6 +42,10 @@
   dependencies:
     acorn "^3.0.4"
 
+acorn@^1.0.3:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014"
+
 acorn@^3.0.4:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
@@ -70,10 +62,6 @@
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/address/-/address-1.0.1.tgz#363f5d3f2be26d0655d8afd5a9562e4fc2194537"
 
-after@~0.8.1:
-  version "0.8.2"
-  resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
-
 ajv-keywords@^1.0.0, ajv-keywords@^1.1.1:
   version "1.5.1"
   resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
@@ -144,10 +132,6 @@
   dependencies:
     color-convert "^1.0.0"
 
-ansi@^0.3.0, ansi@~0.3.1:
-  version "0.3.1"
-  resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21"
-
 anymatch@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
@@ -178,10 +162,6 @@
   dependencies:
     sprintf-js "~1.0.2"
 
-argsarray@0.0.1:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb"
-
 aria-query@^0.5.0:
   version "0.5.0"
   resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-0.5.0.tgz#85e3152cd8cc5bab18dbed61cd9c4fce54fa79c3"
@@ -221,13 +201,6 @@
     define-properties "^1.1.2"
     es-abstract "^1.7.0"
 
-array-index@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/array-index/-/array-index-1.0.0.tgz#ec56a749ee103e4e08c790b9c353df16055b97f9"
-  dependencies:
-    debug "^2.2.0"
-    es6-symbol "^3.0.2"
-
 array-map@~0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662"
@@ -288,6 +261,10 @@
   version "0.0.7"
   resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
 
+ast-types@0.8.15:
+  version "0.8.15"
+  resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.8.15.tgz#8eef0827f04dff0ec8857ba925abe3fea6194e52"
+
 async-each@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
@@ -983,6 +960,10 @@
   version "0.4.2"
   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
 
+base62@0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/base62/-/base62-0.1.1.tgz#7b4174c2f94449753b11c2651c083da841a7b084"
+
 base64-js@^1.0.2:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1"
@@ -1005,22 +986,6 @@
   version "1.8.0"
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774"
 
-bindings@~1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"
-
-bl@^1.0.0:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e"
-  dependencies:
-    readable-stream "^2.0.5"
-
-bl@~1.0.0:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/bl/-/bl-1.0.3.tgz#fc5421a28fd4226036c3b3891a66a25bc64d226e"
-  dependencies:
-    readable-stream "~2.0.5"
-
 block-stream@*:
   version "0.0.9"
   resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
@@ -1165,12 +1130,6 @@
   dependencies:
     node-int64 "^0.4.0"
 
-buffer-from@0.1.1:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.1.tgz#57b18b1da0a19ec06f33837a5275a242351bd75e"
-  dependencies:
-    is-array-buffer-x "^1.0.13"
-
 buffer-shims@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
@@ -1321,10 +1280,6 @@
   optionalDependencies:
     fsevents "^1.0.0"
 
-chownr@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
-
 ci-info@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534"
@@ -1391,10 +1346,6 @@
     strip-ansi "^3.0.1"
     wrap-ansi "^2.0.0"
 
-clone-buffer@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
-
 clone@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149"
@@ -1803,18 +1754,18 @@
   dependencies:
     ms "0.7.1"
 
-debug@2.6.1, debug@^2.1.1, debug@^2.2.0, debug@^2.3.2, debug@^2.6.0:
-  version "2.6.1"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351"
-  dependencies:
-    ms "0.7.2"
-
 debug@2.6.7:
   version "2.6.7"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
   dependencies:
     ms "2.0.0"
 
+debug@^2.1.1, debug@^2.2.0, debug@^2.3.2, debug@^2.6.0:
+  version "2.6.1"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351"
+  dependencies:
+    ms "0.7.2"
+
 debug@^2.6.3, debug@^2.6.6:
   version "2.6.8"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
@@ -1839,12 +1790,6 @@
   dependencies:
     strip-bom "^2.0.0"
 
-deferred-leveldown@~1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.1.tgz#5d25c3310f5fe909946f6240dc9f90dd109a71ef"
-  dependencies:
-    abstract-leveldown "~2.4.0"
-
 define-properties@^1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
@@ -1997,22 +1942,12 @@
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d"
 
-double-ended-queue@2.1.0-0:
-  version "2.1.0-0"
-  resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
-
 duplexer2@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
   dependencies:
     readable-stream "^2.0.2"
 
-duplexer2@~0.0.2:
-  version "0.0.2"
-  resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db"
-  dependencies:
-    readable-stream "~1.1.9"
-
 duplexer@^0.1.1, duplexer@~0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
@@ -2061,18 +1996,6 @@
   dependencies:
     iconv-lite "~0.4.13"
 
-end-of-stream@^1.0.0, end-of-stream@^1.1.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
-  dependencies:
-    once "^1.4.0"
-
-end-stream@~0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/end-stream/-/end-stream-0.1.0.tgz#32003f3f438a2b0143168137f8fa6e9866c81ed5"
-  dependencies:
-    write-stream "~0.4.3"
-
 enhanced-resolve@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.1.0.tgz#9f4b626f577245edcf4b2ad83d86e17f4f421dec"
@@ -2101,7 +2024,7 @@
     prop-types "^15.5.4"
     uuid "^2.0.3"
 
-"errno@>=0.1.1 <0.2.0-0", errno@^0.1.3, errno@~0.1.1:
+"errno@>=0.1.1 <0.2.0-0", errno@^0.1.3:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
   dependencies:
@@ -2130,6 +2053,14 @@
     is-date-object "^1.0.1"
     is-symbol "^1.0.1"
 
+es3ify@^0.1.3:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/es3ify/-/es3ify-0.1.4.tgz#ad9fa5df1ae34f3f31e1211b5818b2d51078dfd1"
+  dependencies:
+    esprima-fb "~3001.0001.0000-dev-harmony-fb"
+    jstransform "~3.0.0"
+    through "~2.3.4"
+
 es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14:
   version "0.10.20"
   resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.20.tgz#72a9b4fd5832797ba1bb65dceb2e25c04241c492"
@@ -2170,7 +2101,7 @@
     es6-symbol "3.1.1"
     event-emitter "~0.3.5"
 
-es6-symbol@3.1.1, es6-symbol@^3.0.2, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1:
+es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
   dependencies:
@@ -2325,6 +2256,10 @@
     text-table "~0.2.0"
     user-home "^2.0.0"
 
+esmangle-evaluator@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/esmangle-evaluator/-/esmangle-evaluator-1.0.1.tgz#620d866ef4861b3311f75766d52a8572bb3c6336"
+
 espree@^3.4.0:
   version "3.4.3"
   resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374"
@@ -2332,6 +2267,14 @@
     acorn "^5.0.1"
     acorn-jsx "^3.0.0"
 
+esprima-fb@~15001.1001.0-dev-harmony-fb:
+  version "15001.1001.0-dev-harmony-fb"
+  resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz#43beb57ec26e8cf237d3dd8b33e42533577f2659"
+
+esprima-fb@~3001.0001.0000-dev-harmony-fb, esprima-fb@~3001.1.0-dev-harmony-fb:
+  version "3001.1.0-dev-harmony-fb"
+  resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz#b77d37abcd38ea0b77426bb8bc2922ce6b426411"
+
 esprima@^2.6.0, esprima@^2.7.1:
   version "2.7.3"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
@@ -2422,12 +2365,6 @@
   dependencies:
     merge "^1.1.3"
 
-execspawn@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/execspawn/-/execspawn-1.0.1.tgz#8286f9dde7cecde7905fbdc04e24f368f23f8da6"
-  dependencies:
-    util-extend "^1.0.1"
-
 exit-hook@^1.0.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
@@ -2444,10 +2381,6 @@
   dependencies:
     fill-range "^2.1.0"
 
-expand-template@^1.0.0:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.0.3.tgz#6c303323177a62b1b22c070279f7861287b69b1a"
-
 express@^4.13.3:
   version "4.15.3"
   resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662"
@@ -2510,9 +2443,14 @@
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
 
-fast-future@~1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/fast-future/-/fast-future-1.0.2.tgz#8435a9aaa02d79248d17d704e76259301d99280a"
+falafel@^1.0.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/falafel/-/falafel-1.2.0.tgz#c18d24ef5091174a497f318cd24b026a25cddab4"
+  dependencies:
+    acorn "^1.0.3"
+    foreach "^2.0.5"
+    isarray "0.0.1"
+    object-keys "^1.0.6"
 
 fast-levenshtein@~2.0.4:
   version "2.0.6"
@@ -2755,16 +2693,6 @@
     function-bind "^1.1.0"
     is-callable "^1.1.2"
 
-gauge@~1.2.5:
-  version "1.2.7"
-  resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93"
-  dependencies:
-    ansi "^0.3.0"
-    has-unicode "^2.0.0"
-    lodash.pad "^4.1.0"
-    lodash.padend "^4.1.0"
-    lodash.padstart "^4.1.0"
-
 gauge@~2.7.3:
   version "2.7.4"
   resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@@ -2818,34 +2746,6 @@
   dependencies:
     assert-plus "^1.0.0"
 
-ghreleases@^1.0.2:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/ghreleases/-/ghreleases-1.0.5.tgz#a20f8194074311e19d84ccba7a6e08c4b434fd80"
-  dependencies:
-    after "~0.8.1"
-    ghrepos "~2.0.0"
-    ghutils "~3.2.0"
-    simple-mime "~0.1.0"
-    url-template "~2.0.6"
-    xtend "~4.0.0"
-
-ghrepos@~2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/ghrepos/-/ghrepos-2.0.0.tgz#d66eae9d98a3b5398e460d6db7e10a742692e81b"
-  dependencies:
-    ghutils "~3.2.0"
-
-ghutils@~3.2.0:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/ghutils/-/ghutils-3.2.1.tgz#4fcedffac935fcace06e12a17c6174e2c29ffe4f"
-  dependencies:
-    jsonist "~1.3.0"
-    xtend "~4.0.1"
-
-github-from-package@0.0.0:
-  version "0.0.0"
-  resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
-
 glob-base@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
@@ -2859,7 +2759,7 @@
   dependencies:
     is-glob "^2.0.0"
 
-"glob@3 || 4 || 5 || 6 || 7", glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@~7.1.1:
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@~7.1.1:
   version "7.1.2"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
   dependencies:
@@ -2966,16 +2866,6 @@
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
 
-has-symbol-support-x@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.2.0.tgz#e624ead5190c35b34e4e299344dff6437db02ce2"
-
-has-to-string-tag-x@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.2.0.tgz#c536dc4dbbebe1be9d28f624fd320f793129fd53"
-  dependencies:
-    has-symbol-support-x "^1.2.0"
-
 has-unicode@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -3164,13 +3054,6 @@
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
 
-hyperquest@~1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/hyperquest/-/hyperquest-1.2.0.tgz#39e1fef66888dc7ce0dec6c0dd814f6fc8944ad5"
-  dependencies:
-    duplexer2 "~0.0.2"
-    through2 "~0.6.3"
-
 iconv-lite@0.4.13, iconv-lite@~0.4.13:
   version "0.4.13"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
@@ -3187,7 +3070,7 @@
   version "3.3.3"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
 
-immediate@3.0.6, immediate@~3.0.5:
+immediate@~3.0.5:
   version "3.0.6"
   resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
 
@@ -3236,6 +3119,13 @@
   version "1.3.4"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
 
+inline-process-browser@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/inline-process-browser/-/inline-process-browser-1.0.0.tgz#46a61b153dd3c9b1624b1a00626edb4f7f414f22"
+  dependencies:
+    falafel "^1.0.1"
+    through2 "^0.6.5"
+
 inquirer@3.0.6:
   version "3.0.6"
   resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347"
@@ -3294,14 +3184,6 @@
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
 
-is-array-buffer-x@^1.0.13:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/is-array-buffer-x/-/is-array-buffer-x-1.2.1.tgz#579180688b612b3691700d6c9ab335d6fd46955c"
-  dependencies:
-    has-to-string-tag-x "^1.2.0"
-    is-object-like-x "^1.2.0"
-    to-string-tag-x "^1.2.0"
-
 is-arrayish@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
@@ -3382,14 +3264,6 @@
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
 
-is-function-x@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/is-function-x/-/is-function-x-1.2.0.tgz#1c839899f07bd23dfc695e4f0655107be852762d"
-  dependencies:
-    has-to-string-tag-x "^1.2.0"
-    is-primitive "^2.0.0"
-    to-string-tag-x "^1.1.1"
-
 is-glob@^2.0.0, is-glob@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
@@ -3429,13 +3303,6 @@
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
 
-is-object-like-x@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/is-object-like-x/-/is-object-like-x-1.2.0.tgz#b5929d8f12ab92daee9d2f754b831844bcc08c21"
-  dependencies:
-    is-function-x "^1.2.0"
-    is-primitive "^2.0.0"
-
 is-path-cwd@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
@@ -3907,7 +3774,7 @@
   dependencies:
     jsonify "~0.0.0"
 
-json-stringify-safe@~5.0.0, json-stringify-safe@~5.0.1:
+json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
 
@@ -3935,15 +3802,6 @@
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
 
-jsonist@~1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/jsonist/-/jsonist-1.3.0.tgz#c0c74b95ef1c952038619b29efa520b1cc987556"
-  dependencies:
-    bl "~1.0.0"
-    hyperquest "~1.2.0"
-    json-stringify-safe "~5.0.0"
-    xtend "~4.0.0"
-
 jsonpointer@^4.0.0:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
@@ -3957,6 +3815,14 @@
     json-schema "0.2.3"
     verror "1.3.6"
 
+jstransform@~3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-3.0.0.tgz#a2591ab6cee8d97bf3be830dbfa2313b87cd640b"
+  dependencies:
+    base62 "0.1.1"
+    esprima-fb "~3001.1.0-dev-harmony-fb"
+    source-map "0.1.31"
+
 jsx-ast-utils@^1.3.4, jsx-ast-utils@^1.4.0:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1"
@@ -3997,57 +3863,6 @@
   dependencies:
     invert-kv "^1.0.0"
 
-level-codec@7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.0.tgz#c755b68d0d44ffa0b1cba044b8f81a55a14ad39b"
-
-level-codec@~6.1.0:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-6.1.0.tgz#f5df0a99582f76dac43855151ab6f4e4d0d60045"
-
-level-errors@^1.0.3, level-errors@~1.0.3:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.4.tgz#3585e623974c737a93755492a43c0267cda4425f"
-  dependencies:
-    errno "~0.1.1"
-
-level-iterator-stream@~1.3.0:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed"
-  dependencies:
-    inherits "^2.0.1"
-    level-errors "^1.0.3"
-    readable-stream "^1.0.33"
-    xtend "^4.0.0"
-
-level-write-stream@1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/level-write-stream/-/level-write-stream-1.0.0.tgz#3f7fbb679a55137c0feb303dee766e12ee13c1dc"
-  dependencies:
-    end-stream "~0.1.0"
-
-leveldown@1.5.0:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-1.5.0.tgz#6b8d3cbea7a4a89aa47444607d7358213e6fcb81"
-  dependencies:
-    abstract-leveldown "~2.6.1"
-    bindings "~1.2.1"
-    fast-future "~1.0.0"
-    nan "~2.4.0"
-    prebuild "^4.1.1"
-
-levelup@1.3.5:
-  version "1.3.5"
-  resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.5.tgz#fa80a972b74011f2537c8b65678bd8b5188e4e66"
-  dependencies:
-    deferred-leveldown "~1.2.1"
-    level-codec "~6.1.0"
-    level-errors "~1.0.3"
-    level-iterator-stream "~1.3.0"
-    prr "~1.0.1"
-    semver "~5.1.0"
-    xtend "~4.0.0"
-
 leven@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
@@ -4059,11 +3874,14 @@
     prelude-ls "~1.1.2"
     type-check "~0.3.2"
 
-lie@3.1.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
-  dependencies:
+lie@3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/lie/-/lie-3.0.2.tgz#ffda21d7bba26f377cad865d3649b2fc8ce39fea"
+  dependencies:
+    es3ify "^0.1.3"
     immediate "~3.0.5"
+    inline-process-browser "^1.0.0"
+    unreachable-branch-transform "^0.3.0"
 
 load-json-file@^1.0.0:
   version "1.1.0"
@@ -4112,6 +3930,12 @@
     emojis-list "^2.0.0"
     json5 "^0.5.0"
 
+localforage@^1.5.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.5.0.tgz#6b994e19b56611fa85df3992df397ac4ab66e815"
+  dependencies:
+    lie "3.0.2"
+
 locate-path@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
@@ -4119,7 +3943,7 @@
     p-locate "^2.0.0"
     path-exists "^3.0.0"
 
-lodash-es@^4.2.0, lodash-es@^4.2.1:
+lodash-es@^4.17.4, lodash-es@^4.2.0, lodash-es@^4.2.1:
   version "4.17.4"
   resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7"
 
@@ -4167,10 +3991,6 @@
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53"
 
-lodash.isnull@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/lodash.isnull/-/lodash.isnull-3.0.0.tgz#fafbe59ea1dca27eed786534039dd84c2e07c56e"
-
 lodash.map@^4.4.0:
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
@@ -4187,18 +4007,6 @@
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55"
 
-lodash.pad@^4.1.0:
-  version "4.5.1"
-  resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70"
-
-lodash.padend@^4.1.0:
-  version "4.6.1"
-  resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e"
-
-lodash.padstart@^4.1.0:
-  version "4.6.1"
-  resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b"
-
 lodash.pick@^4.2.1:
   version "4.4.0"
   resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
@@ -4272,10 +4080,6 @@
     pseudomap "^1.0.1"
     yallist "^2.0.0"
 
-ltgt@2.1.3:
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34"
-
 macaddress@^0.2.8:
   version "0.2.8"
   resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"
@@ -4391,23 +4195,23 @@
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
 
-minimatch@3, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2:
-  version "3.0.4"
-  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
-  dependencies:
-    brace-expansion "^1.1.7"
-
 minimatch@3.0.3:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
   dependencies:
     brace-expansion "^1.0.0"
 
+minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+  dependencies:
+    brace-expansion "^1.1.7"
+
 minimist@0.0.8, minimist@~0.0.1:
   version "0.0.8"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
 
-minimist@^1.1.1, minimist@^1.1.2, minimist@^1.1.3, minimist@^1.2.0:
+minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
 
@@ -4441,7 +4245,7 @@
   version "0.0.7"
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
 
-nan@^2.3.0, nan@^2.3.2, nan@~2.4.0:
+nan@^2.3.0, nan@^2.3.2:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.4.0.tgz#fb3c59d45fe4effe215f0b890f8adf6eb32d2232"
 
@@ -4472,7 +4276,7 @@
     encoding "^0.1.11"
     is-stream "^1.0.1"
 
-node-gyp@^3.0.3, node-gyp@^3.3.1:
+node-gyp@^3.3.1:
   version "3.6.1"
   resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.1.tgz#19561067ff185464aded478212681f47fd578cbc"
   dependencies:
@@ -4522,25 +4326,6 @@
     util "^0.10.3"
     vm-browserify "0.0.4"
 
-node-ninja@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/node-ninja/-/node-ninja-1.0.2.tgz#20a09e57b92e2df591993d4bf098ac3e727062b6"
-  dependencies:
-    fstream "^1.0.0"
-    glob "3 || 4 || 5 || 6 || 7"
-    graceful-fs "^4.1.2"
-    minimatch "3"
-    mkdirp "^0.5.0"
-    nopt "2 || 3"
-    npmlog "0 || 1 || 2"
-    osenv "0"
-    path-array "^1.0.0"
-    request "2"
-    rimraf "2"
-    semver "2.x || 3.x || 4 || 5"
-    tar "^2.0.0"
-    which "1"
-
 node-notifier@^5.0.2:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.1.2.tgz#2fa9e12605fa10009d44549d6fcd8a63dde0e4ff"
@@ -4604,10 +4389,6 @@
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f"
 
-noop-logger@^0.1.0:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
-
 "nopt@2 || 3":
   version "3.0.6"
   resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
@@ -4661,14 +4442,6 @@
     shell-quote "^1.6.1"
     string.prototype.padend "^3.0.0"
 
-"npmlog@0 || 1 || 2", npmlog@^2.0.0:
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692"
-  dependencies:
-    ansi "~0.3.1"
-    are-we-there-yet "~1.1.2"
-    gauge "~1.2.5"
-
 "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5"
@@ -4712,7 +4485,7 @@
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6"
 
-object-keys@^1.0.10, object-keys@^1.0.8:
+object-keys@^1.0.10, object-keys@^1.0.6, object-keys@^1.0.8:
   version "1.0.11"
   resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
 
@@ -4763,7 +4536,7 @@
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
 
-once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0:
+once@^1.3.0, once@^1.3.3, once@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
   dependencies:
@@ -4907,12 +4680,6 @@
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
 
-path-array@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/path-array/-/path-array-1.0.1.tgz#7e2f0f35f07a2015122b868b7eac0eb2c4fec271"
-  dependencies:
-    array-index "^1.0.0"
-
 path-browserify@0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
@@ -5305,136 +5072,6 @@
     source-map "^0.5.6"
     supports-color "^3.2.3"
 
-pouchdb-abstract-mapreduce@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-abstract-mapreduce/-/pouchdb-abstract-mapreduce-6.2.0.tgz#55858d1799c89290185df56b71c843a481abcbae"
-  dependencies:
-    pouchdb-binary-utils "6.2.0"
-    pouchdb-collate "6.2.0"
-    pouchdb-collections "6.2.0"
-    pouchdb-mapreduce-utils "6.2.0"
-    pouchdb-md5 "6.2.0"
-    pouchdb-promise "6.2.0"
-    pouchdb-utils "6.2.0"
-
-pouchdb-binary-utils@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-binary-utils/-/pouchdb-binary-utils-6.2.0.tgz#dc4154c01b92fb9ad87fdf695394a91b5d9429bf"
-  dependencies:
-    buffer-from "0.1.1"
-
-pouchdb-collate@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-collate/-/pouchdb-collate-6.2.0.tgz#9ee5e578de004581c148754f7decdc0b70495ffc"
-
-pouchdb-collections@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-collections/-/pouchdb-collections-6.2.0.tgz#f532601870cbd329ba0c6005bcdd301126825be2"
-
-pouchdb-errors@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-errors/-/pouchdb-errors-6.2.0.tgz#5ccbefaf2b92e918d5d90b5a5b779376464b5907"
-  dependencies:
-    inherits "2.0.3"
-
-pouchdb-find@^6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-find/-/pouchdb-find-6.2.0.tgz#a824e158e25b0816614d67e680a4d8c8a694fa1e"
-  dependencies:
-    pouchdb-abstract-mapreduce "6.2.0"
-    pouchdb-collate "6.2.0"
-    pouchdb-md5 "6.2.0"
-    pouchdb-promise "6.2.0"
-    pouchdb-selector-core "6.2.0"
-    pouchdb-utils "6.2.0"
-
-pouchdb-mapreduce-utils@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-mapreduce-utils/-/pouchdb-mapreduce-utils-6.2.0.tgz#fe6c15eff1a6fe48d68f973c7a79ef492652ca2f"
-  dependencies:
-    argsarray "0.0.1"
-    inherits "2.0.3"
-    pouchdb-collections "6.2.0"
-    pouchdb-utils "6.2.0"
-
-pouchdb-md5@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-md5/-/pouchdb-md5-6.2.0.tgz#7581fc4e932c57c78ee48d25a7d0014bff008e4d"
-  dependencies:
-    pouchdb-binary-utils "6.2.0"
-    spark-md5 "3.0.0"
-
-pouchdb-promise@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-promise/-/pouchdb-promise-6.2.0.tgz#1e4fcec0aa0678df583e6a7b4b996ba010a608fe"
-  dependencies:
-    lie "3.1.1"
-
-pouchdb-selector-core@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-selector-core/-/pouchdb-selector-core-6.2.0.tgz#ab753c17182bc394e6a6b1de275331161f85e325"
-  dependencies:
-    pouchdb-collate "6.2.0"
-    pouchdb-utils "6.2.0"
-
-pouchdb-utils@6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb-utils/-/pouchdb-utils-6.2.0.tgz#cd8d4207a34e478b49af201ff0c51ea733244061"
-  dependencies:
-    argsarray "0.0.1"
-    clone-buffer "1.0.0"
-    immediate "3.0.6"
-    inherits "2.0.3"
-    pouchdb-collections "6.2.0"
-    pouchdb-errors "6.2.0"
-    pouchdb-promise "6.2.0"
-
-pouchdb@^6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-6.2.0.tgz#5c8521b46cfc83644ca7fc61a7b240d2ce17dc0d"
-  dependencies:
-    argsarray "0.0.1"
-    buffer-from "0.1.1"
-    clone-buffer "1.0.0"
-    debug "2.6.1"
-    double-ended-queue "2.1.0-0"
-    immediate "3.0.6"
-    inherits "2.0.3"
-    level-codec "7.0.0"
-    level-write-stream "1.0.0"
-    leveldown "1.5.0"
-    levelup "1.3.5"
-    lie "3.1.1"
-    ltgt "2.1.3"
-    readable-stream "1.0.33"
-    request "2.80.0"
-    spark-md5 "3.0.0"
-    through2 "2.0.3"
-    vuvuzela "1.0.3"
-
-prebuild@^4.1.1:
-  version "4.5.0"
-  resolved "https://registry.yarnpkg.com/prebuild/-/prebuild-4.5.0.tgz#2aaa0df2063bff814a803bd4dc94ff9b64e5df00"
-  dependencies:
-    async "^1.4.0"
-    execspawn "^1.0.1"
-    expand-template "^1.0.0"
-    ghreleases "^1.0.2"
-    github-from-package "0.0.0"
-    minimist "^1.1.2"
-    mkdirp "^0.5.1"
-    node-gyp "^3.0.3"
-    node-ninja "^1.0.1"
-    noop-logger "^0.1.0"
-    npmlog "^2.0.0"
-    os-homedir "^1.0.1"
-    pump "^1.0.0"
-    rc "^1.0.3"
-    simple-get "^1.4.2"
-    tar-fs "^1.7.0"
-    tar-stream "^1.2.1"
-    xtend "^4.0.1"
-
 prelude-ls@~1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -5465,7 +5102,7 @@
     ansi-regex "^2.1.1"
     ansi-styles "^3.0.0"
 
-private@^0.1.6:
+private@^0.1.6, private@~0.1.5:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"
 
@@ -5505,10 +5142,6 @@
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
 
-prr@~1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
-
 ps-tree@^1.0.1:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
@@ -5529,13 +5162,6 @@
     parse-asn1 "^5.0.0"
     randombytes "^2.0.1"
 
-pump@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.2.tgz#3b3ee6512f94f0e575538c17995f9f16990a5d51"
-  dependencies:
-    end-of-stream "^1.1.0"
-    once "^1.3.1"
-
 punycode@1.3.2:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
@@ -5594,7 +5220,7 @@
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
 
-rc@^1.0.1, rc@^1.0.3, rc@^1.1.6, rc@^1.1.7:
+rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
   dependencies:
@@ -5805,7 +5431,7 @@
     normalize-package-data "^2.3.2"
     path-type "^2.0.0"
 
-readable-stream@1.0, readable-stream@1.0.33, "readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@^1.0.33:
+readable-stream@1.0, "readable-stream@>=1.0.33-1 <1.1.0-0":
   version "1.0.33"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.33.tgz#3a360dd66c1b1d7fd4705389860eda1d0f61126c"
   dependencies:
@@ -5814,7 +5440,7 @@
     isarray "0.0.1"
     string_decoder "~0.10.x"
 
-readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6:
+readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6:
   version "2.2.9"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8"
   dependencies:
@@ -5826,30 +5452,6 @@
     string_decoder "~1.0.0"
     util-deprecate "~1.0.1"
 
-readable-stream@~0.0.2:
-  version "0.0.4"
-  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-0.0.4.tgz#f32d76e3fb863344a548d79923007173665b3b8d"
-
-readable-stream@~1.1.9:
-  version "1.1.14"
-  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
-  dependencies:
-    core-util-is "~1.0.0"
-    inherits "~2.0.1"
-    isarray "0.0.1"
-    string_decoder "~0.10.x"
-
-readable-stream@~2.0.5:
-  version "2.0.6"
-  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
-  dependencies:
-    core-util-is "~1.0.0"
-    inherits "~2.0.1"
-    isarray "~1.0.0"
-    process-nextick-args "~1.0.6"
-    string_decoder "~0.10.x"
-    util-deprecate "~1.0.1"
-
 readdirp@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
@@ -5867,6 +5469,15 @@
     is-fullwidth-code-point "^1.0.0"
     mute-stream "0.0.5"
 
+recast@^0.10.1:
+  version "0.10.43"
+  resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.43.tgz#b95d50f6d60761a5f6252e15d80678168491ce7f"
+  dependencies:
+    ast-types "0.8.15"
+    esprima-fb "~15001.1001.0-dev-harmony-fb"
+    private "~0.1.5"
+    source-map "~0.5.0"
+
 rechoir@^0.6.2:
   version "0.6.2"
   resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
@@ -5900,14 +5511,31 @@
   dependencies:
     balanced-match "^0.4.2"
 
-redux-history-transitions@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/redux-history-transitions/-/redux-history-transitions-2.2.0.tgz#1d5197f0e586a693d65d84109d14f79bd695f919"
-
 redux-immutable@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/redux-immutable/-/redux-immutable-4.0.0.tgz#3a1a32df66366462b63691f0e1dc35e472bbc9f3"
 
+redux-offline@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/redux-offline/-/redux-offline-2.0.0.tgz#5896e95477417c8173e083f4f2d977466ec91808"
+  dependencies:
+    redux-persist "^4.5.0"
+
+redux-persist-transform-immutable@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/redux-persist-transform-immutable/-/redux-persist-transform-immutable-4.3.0.tgz#24720c99f0707dd99e920b95f851ae3d1baa6ed8"
+  dependencies:
+    transit-immutable-js "^0.7.0"
+    transit-js "^0.8.846"
+
+redux-persist@^4.5.0:
+  version "4.8.0"
+  resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-4.8.0.tgz#17fd998949bdeef9275e4cf60ad5bbe1c73675fc"
+  dependencies:
+    json-stringify-safe "^5.0.1"
+    lodash "^4.17.4"
+    lodash-es "^4.17.4"
+
 redux-saga@^0.15.3:
   version "0.15.3"
   resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-0.15.3.tgz#be2b86b4ad46bf0d84fcfcb0ca96cfc33db91acb"
@@ -6015,7 +5643,7 @@
   dependencies:
     is-finite "^1.0.0"
 
-request@2, request@2.80.0, request@^2.79.0:
+request@2, request@^2.79.0:
   version "2.80.0"
   resolved "https://registry.yarnpkg.com/request/-/request-2.80.0.tgz#8cc162d76d79381cdefdd3505d76b80b60589bd0"
   dependencies:
@@ -6218,11 +5846,11 @@
   dependencies:
     semver "^5.0.3"
 
-"semver@2 || 3 || 4 || 5", semver@~5.1.0:
+"semver@2 || 3 || 4 || 5":
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.1.1.tgz#a3292a373e6f3e0798da0b20641b9a9c5bc47e19"
 
-"semver@2.x || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0:
+semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0:
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
 
@@ -6334,18 +5962,6 @@
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
 
-simple-get@^1.4.2:
-  version "1.4.3"
-  resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-1.4.3.tgz#e9755eda407e96da40c5e5158c9ea37b33becbeb"
-  dependencies:
-    once "^1.3.1"
-    unzip-response "^1.0.0"
-    xtend "^4.0.0"
-
-simple-mime@~0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/simple-mime/-/simple-mime-0.1.0.tgz#95f517c4f466d7cff561a71fc9dab2596ea9ef2e"
-
 slash@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
@@ -6433,7 +6049,13 @@
   dependencies:
     source-map "^0.5.6"
 
-source-map@0.5.6, source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3:
+source-map@0.1.31:
+  version "0.1.31"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.31.tgz#9f704d0d69d9e138a81badf6ebb4fde33d151c61"
+  dependencies:
+    amdefine ">=0.0.4"
+
+source-map@0.5.6, source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3:
   version "0.5.6"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
 
@@ -6449,10 +6071,6 @@
   dependencies:
     amdefine ">=0.0.4"
 
-spark-md5@3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.0.tgz#3722227c54e2faf24b1dc6d933cc144e6f71bfef"
-
 spdx-correct@~1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
@@ -6699,15 +6317,6 @@
   version "0.2.6"
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.6.tgz#206be8e188860b514425375e6f1ae89bfb01fd8d"
 
-tar-fs@^1.7.0:
-  version "1.15.2"
-  resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.15.2.tgz#761f5b32932c7b39461a60d537faea0d8084830c"
-  dependencies:
-    chownr "^1.0.1"
-    mkdirp "^0.5.1"
-    pump "^1.0.0"
-    tar-stream "^1.1.2"
-
 tar-pack@^3.4.0:
   version "3.4.0"
   resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984"
@@ -6721,15 +6330,6 @@
     tar "^2.2.1"
     uid-number "^0.0.6"
 
-tar-stream@^1.1.2, tar-stream@^1.2.1:
-  version "1.5.4"
-  resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016"
-  dependencies:
-    bl "^1.0.0"
-    end-of-stream "^1.0.0"
-    readable-stream "^2.0.0"
-    xtend "^4.0.0"
-
 tar@^2.0.0, tar@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
@@ -6756,21 +6356,14 @@
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/throat/-/throat-3.0.0.tgz#e7c64c867cbb3845f10877642f7b60055b8ec0d6"
 
-through2@2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
-  dependencies:
-    readable-stream "^2.1.5"
-    xtend "~4.0.1"
-
-through2@~0.6.3:
+through2@^0.6.2, through2@^0.6.5:
   version "0.6.5"
   resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48"
   dependencies:
     readable-stream ">=1.0.33-1 <1.1.0-0"
     xtend ">=4.0.0 <4.1.0-0"
 
-through@2, through@^2.3.6, through@~2.3, through@~2.3.1:
+through@2, through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.4:
   version "2.3.8"
   resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
 
@@ -6802,13 +6395,6 @@
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
 
-to-string-tag-x@^1.1.1, to-string-tag-x@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/to-string-tag-x/-/to-string-tag-x-1.2.0.tgz#22d8861bedde2db8f18e2da0a002a843e56e0135"
-  dependencies:
-    lodash.isnull "^3.0.0"
-    validate.io-undefined "^1.0.3"
-
 toposort@^1.0.0:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.3.tgz#f02cd8a74bd8be2fc0e98611c3bacb95a171869c"
@@ -6823,6 +6409,14 @@
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
 
+transit-immutable-js@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/transit-immutable-js/-/transit-immutable-js-0.7.0.tgz#993e25089b6311ff402140f556276d6d253005d9"
+
+transit-js@^0.8.846:
+  version "0.8.846"
+  resolved "https://registry.yarnpkg.com/transit-js/-/transit-js-0.8.846.tgz#76e06e8f0e6be27675e3442112f5c9bb75343464"
+
 trim-newlines@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
@@ -6930,7 +6524,15 @@
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
 
-unzip-response@^1.0.0, unzip-response@^1.0.2:
+unreachable-branch-transform@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/unreachable-branch-transform/-/unreachable-branch-transform-0.3.0.tgz#d99cc4c6e746d264928845b611db54b0f3474caa"
+  dependencies:
+    esmangle-evaluator "^1.0.0"
+    recast "^0.10.1"
+    through2 "^0.6.2"
+
+unzip-response@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe"
 
@@ -6982,10 +6584,6 @@
     querystringify "~1.0.0"
     requires-port "1.0.x"
 
-url-template@~2.0.6:
-  version "2.0.8"
-  resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21"
-
 url@^0.11.0:
   version "0.11.0"
   resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
@@ -7003,10 +6601,6 @@
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
 
-util-extend@^1.0.1:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f"
-
 util@0.10.3, util@^0.10.3:
   version "0.10.3"
   resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
@@ -7040,10 +6634,6 @@
     spdx-correct "~1.0.0"
     spdx-expression-parse "~1.0.0"
 
-validate.io-undefined@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/validate.io-undefined/-/validate.io-undefined-1.0.3.tgz#7e27fcbb315b841e78243431897671929e20b7f4"
-
 value-equal@^0.2.0:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.2.1.tgz#c220a304361fce6994dbbedaa3c7e1a1b895871d"
@@ -7068,10 +6658,6 @@
   dependencies:
     indexof "0.0.1"
 
-vuvuzela@1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b"
-
 walker@~1.0.5:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
@@ -7279,12 +6865,6 @@
     imurmurhash "^0.1.4"
     slide "^1.1.5"
 
-write-stream@~0.4.3:
-  version "0.4.3"
-  resolved "https://registry.yarnpkg.com/write-stream/-/write-stream-0.4.3.tgz#83cc8c0347d0af6057a93862b4e3ae01de5c81c1"
-  dependencies:
-    readable-stream "~0.0.2"
-
 write@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
@@ -7305,7 +6885,7 @@
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635"
 
-"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
+"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"