From 2cf01b8f25d40517f33e837cc95f98d9f72ff352 Mon Sep 17 00:00:00 2001
From: Timotej Ecimovic <timotej.ecimovic@silabs.com>
Date: Tue, 12 May 2020 07:48:38 -0400
Subject: [PATCH] Latest snapshot.

---
 Jenkinsfile                                   |    4 +-
 apack.info                                    |   29 +
 docs/api.md                                   |  909 ++++-
 docs/design.md                                |   47 +-
 docs/zap-schema.svg                           |  554 ++-
 package-lock.json                             | 3557 +++++++++++------
 package.json                                  |   24 +-
 quasar.conf.js                                |    5 +-
 src-electron/db/db-api.js                     |    8 +-
 src-electron/db/query-config.js               |  485 +++
 src-electron/db/query-generic.js              |   50 +
 src-electron/db/query-package.js              |   70 +
 src-electron/db/query-session.js              |  137 +
 src-electron/db/{query.js => query-zcl.js}    |  492 +--
 src-electron/db/zap-schema.sql                |  239 +-
 src-electron/generator/static_generator.js    |   10 +-
 .../handlebars/helpers/helper_utils.js        |   67 +
 src-electron/main-process/args.js             |    5 +-
 src-electron/main-process/electron-main.js    |   14 +-
 src-electron/main-process/importexport.js     |  126 +-
 src-electron/main-process/menu.js             |  315 +-
 src-electron/main-process/window.js           |   60 +-
 src-electron/rest/generation.js               |   69 +-
 src-electron/rest/static-zcl.js               |   21 +
 src-electron/rest/user-data.js                |  183 +-
 src-electron/server/http-server.js            |    8 +-
 src-electron/zcl/zcl-loader.js                |   21 +-
 src-electron/zcl/zcl-model.js                 |  103 +-
 src/api/renderer_api.js                       |   19 +
 src/boot/axios.js                             |    1 -
 src/boot/globalapi.js                         |    7 +
 src/components/ZclAttributeView.vue           |   84 +-
 src/components/ZclClusterDetail.vue           |   40 +-
 src/components/ZclClusterInfo.vue             |   28 +-
 src/components/ZclClusterList.vue             |   40 +-
 src/components/ZclCommandView.vue             |   67 +-
 src/components/ZclEndpointConfig.vue          |   64 +-
 src/components/ZclEndpointTypeConfig.vue      |   85 +-
 src/components/ZclReportingView.vue           |   74 +-
 src/layouts/ZclClusterLayout.vue              |    4 +-
 src/layouts/ZclLayout.vue                     |   18 +
 src/store/zap/actions.js                      |  143 +-
 src/store/zap/mutations.js                    |   72 +
 src/store/zap/state.js                        |   13 +-
 test/generation.test.js                       |   26 +-
 test/query.test.js                            |  102 +-
 test/rendererapi.test.js                      |    6 +
 test/server.test.js                           |    5 +-
 test/zcl-loader.test.js                       |    2 +-
 zcl/general.xml                               |    2 +-
 .../af-structs.handlebars                     |   48 +
 .../att-storage.handlebars                    |   57 +
 .../print-cluster.handlebars                  |   25 +
 zcl/wwah-silabs.xml                           |  148 +-
 54 files changed, 6470 insertions(+), 2322 deletions(-)
 create mode 100644 apack.info
 create mode 100644 src-electron/db/query-config.js
 create mode 100644 src-electron/db/query-generic.js
 create mode 100644 src-electron/db/query-package.js
 create mode 100644 src-electron/db/query-session.js
 rename src-electron/db/{query.js => query-zcl.js} (50%)
 create mode 100644 src/api/renderer_api.js
 create mode 100644 src/boot/globalapi.js
 create mode 100644 test/rendererapi.test.js
 create mode 100644 zcl/generation-templates/af-structs.handlebars
 create mode 100644 zcl/generation-templates/att-storage.handlebars
 create mode 100644 zcl/generation-templates/print-cluster.handlebars

diff --git a/Jenkinsfile b/Jenkinsfile
index 1dd31596..2d56861b 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -85,10 +85,10 @@ pipeline
                 script 
                 {
                     zip archive: true, dir: './dist/electron/zap-linux-x64', glob: '', zipFile: 'zap-linux-x64.zip'
-                    zip archive: true, dir: './dist/electron/zap-linux-ia32', glob: '', zipFile: 'zap-linux-ia32.zip'
                     zip archive: true, dir: './dist/electron/zap-darwin-x64', glob: '', zipFile: 'zap-darwin-x64.zip'
-                    zip archive: true, dir: './dist/electron/zap-win32-ia32', glob: '', zipFile: 'zap-win32-ia32.zip'
                     zip archive: true, dir: './dist/electron/zap-win32-x64', glob: '', zipFile: 'zap-win32-x64.zip'
+                    //zip archive: true, dir: './dist/electron/zap-linux-ia32', glob: '', zipFile: 'zap-linux-ia32.zip'
+                    //zip archive: true, dir: './dist/electron/zap-win32-ia32', glob: '', zipFile: 'zap-win32-ia32.zip'
                     archiveArtifacts artifacts:'generated-html/**', fingerprint: true
                 }
             }
diff --git a/apack.info b/apack.info
new file mode 100644
index 00000000..a55181fd
--- /dev/null
+++ b/apack.info
@@ -0,0 +1,29 @@
+# Adapter pack file for Studio.
+#
+label=Zigbee Advanced platform
+path=.,dist/electron/zap-linux-x64/
+requiredFeatureLevel=apack.core:4
+
+executable(zap:linux.x86_64) {
+  exe=zap
+}
+
+function(run) {
+  cmd=$(zap) --zclProperties zcl/zcl-studio.properties
+}
+
+function(zapHelp) {
+  cmd=$(zap) --help
+}
+
+function(zapSelfcheck) {
+  cmd=$(zap) --selfCheck
+}
+
+function(zapServer) {
+  cmd=$(zap) --noUi --showUrl --zclProperties zcl/zcl-studio.properties
+}
+
+function(zapFull) {
+  cmd=$(zap) --showUrl --zclProperties zcl/zcl-studio.properties
+}
diff --git a/docs/api.md b/docs/api.md
index e61974e0..e0cb7dea 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -4,8 +4,20 @@
 <dt><a href="#module_JS API_ low level database access">JS API: low level database access</a></dt>
 <dd><p>This module provides generic DB functions for performing SQL queries.</p>
 </dd>
-<dt><a href="#module_JS API_ database queries">JS API: database queries</a></dt>
-<dd><p>Contains all the application queries.</p>
+<dt><a href="#module_DB API_ user configuration queries against the database.">DB API: user configuration queries against the database.</a></dt>
+<dd><p>This module provides queries for user configuration.</p>
+</dd>
+<dt><a href="#module_DB API_ generic queries against the database.">DB API: generic queries against the database.</a></dt>
+<dd><p>This module provides generic queries.</p>
+</dd>
+<dt><a href="#module_DB API_ package-based queries.">DB API: package-based queries.</a></dt>
+<dd><p>This module provides queries related to packages.</p>
+</dd>
+<dt><a href="#module_DB API_ session related queries.">DB API: session related queries.</a></dt>
+<dd><p>This module provides session related queries.</p>
+</dd>
+<dt><a href="#module_DB API_ zcl database access">DB API: zcl database access</a></dt>
+<dd><p>This module provides queries for ZCL static queries.</p>
 </dd>
 <dt><a href="#module_JS API_ generator logic">JS API: generator logic</a></dt>
 <dd><p>Copyright (c) 2020 Silicon Labs. All rights reserved.</p>
@@ -30,31 +42,58 @@
 ## Functions
 
 <dl>
-<dt><a href="#generateInDir">generateInDir()</a></dt>
-<dd><p>Given: Browser Window
-Returns: N/A
-Description: This function gets the directory where user wants the output and
-calls generateCode function which generates the code in the user selected
-output.</p>
+<dt><a href="#processCommandLineArguments">processCommandLineArguments(argv)</a> ⇒</dt>
+<dd><p>Process the command line arguments and resets the state in this file
+to the specified values.</p>
+</dd>
+<dt><a href="#importDataFromFile">importDataFromFile(sessionId, filePath)</a> ⇒</dt>
+<dd><p>Take a given session ID and import the data from the file</p>
 </dd>
-<dt><a href="#setHandlebarTemplateDirectory">setHandlebarTemplateDirectory()</a></dt>
-<dd><p>Given: Browser Window
-Returns: N/A
-Description: This function gets the directory where user wants the output and
+<dt><a href="#writeStateToDatabase">writeStateToDatabase(sessionId, state)</a> ⇒</dt>
+<dd><p>Given a state object, this method returns a promise that resolves
+with the succesfull writing into the database.</p>
+</dd>
+<dt><a href="#exportDataIntoFile">exportDataIntoFile(db, sessionId, filePath)</a> ⇒</dt>
+<dd><p>Toplevel file that takes a given session ID and exports the data into the file</p>
+</dd>
+<dt><a href="#createStateFromDatabase">createStateFromDatabase(db, sessionId)</a> ⇒</dt>
+<dd><p>Given a database and a session id, this method returns a promise that
+resolves with a state object that needs to be saved into a file.</p>
+</dd>
+<dt><a href="#doOpen">doOpen(menuItem, browserWindow, event)</a></dt>
+<dd><p>Perform a file-&gt;open operation.</p>
+</dd>
+<dt><a href="#doSave">doSave(menuItem, browserWindow, event)</a></dt>
+<dd><p>Perform a save, defering to save as if file is not yet selected.</p>
+</dd>
+<dt><a href="#doSaveAs">doSaveAs(menuItem, browserWindow, event)</a></dt>
+<dd><p>Perform save as.</p>
+</dd>
+<dt><a href="#generateInDir">generateInDir(browserWindow)</a></dt>
+<dd><p>This function gets the directory where user wants the output and
 calls generateCode function which generates the code in the user selected
 output.</p>
 </dd>
-<dt><a href="#generateCode">generateCode()</a></dt>
-<dd><p>Given: N/A
-Returns: N/A
-Description: This function generates the code into the user defined directory using promises</p>
+<dt><a href="#setHandlebarTemplateDirectory">setHandlebarTemplateDirectory(browserWindow)</a></dt>
+<dd><p>This function gets the directory where user wants the output and calls 
+generateCode function which generates the code in the user selected output.</p>
 </dd>
-<dt><a href="#resolveGenerationDirectory">resolveGenerationDirectory()</a></dt>
-<dd><p>Given: a map and a generation directory path.
-Return: a map which has the generation directory.
-Description: Resolve the generation directory to be able to generate to the
+<dt><a href="#generateCode">generateCode(db)</a></dt>
+<dd><p>This function generates the code into the user defined directory using promises</p>
+</dd>
+<dt><a href="#fileSave">fileSave(db, winId, filePath)</a> ⇒</dt>
+<dd><p>perform the save.</p>
+</dd>
+<dt><a href="#fileOpen">fileOpen(db, winId, filePaths)</a></dt>
+<dd><p>Perform the do open action.</p>
+</dd>
+<dt><a href="#resolveGenerationDirectory">resolveGenerationDirectory(map)</a> ⇒</dt>
+<dd><p>Description: Resolve the generation directory to be able to generate to the
 correct directory.</p>
 </dd>
+<dt><a href="#initMenu">initMenu(port)</a></dt>
+<dd><p>Initialize a menu.</p>
+</dd>
 </dl>
 
 <a name="module_JS API_ low level database access"></a>
@@ -240,119 +279,117 @@ Returns a promise to insert or replace a version of the application into the dat
 | db | <code>\*</code> | 
 | version | <code>\*</code> | 
 
-<a name="module_JS API_ database queries"></a>
+<a name="module_DB API_ user configuration queries against the database."></a>
 
-## JS API: database queries
-Contains all the application queries.
+## DB API: user configuration queries against the database.
+This module provides queries for user configuration.
 
 
-* [JS API: database queries](#module_JS API_ database queries)
-    * [.insertDomains(db, packageId, data)](#module_JS API_ database queries.insertDomains) ⇒
-    * [.insertStructs(db, packageId, data)](#module_JS API_ database queries.insertStructs) ⇒
-    * [.insertBitmaps(db, packageId, data)](#module_JS API_ database queries.insertBitmaps) ⇒
-    * [.deleteSession(db, sessionId)](#module_JS API_ database queries.deleteSession) ⇒
-    * [.updateKeyValue(db, sessionId, key, value)](#module_JS API_ database queries.updateKeyValue) ⇒
-    * [.insertOrReplaceClusterState(db, endpointTypeId, clusterId, side, enabled)](#module_JS API_ database queries.insertOrReplaceClusterState) ⇒
-    * [.insertEndpoint(db, sessionId, endpointId, endpointTypeRef, networkId)](#module_JS API_ database queries.insertEndpoint) ⇒
-    * [.insertEndpointType(db, sessionId, name, deviceTypeRef)](#module_JS API_ database queries.insertEndpointType) ⇒
-    * [.getAllSesionKeyValues(db, sessionId)](#module_JS API_ database queries.getAllSesionKeyValues) ⇒
-    * [.getAllEndpointTypes(db, sessionId)](#module_JS API_ database queries.getAllEndpointTypes) ⇒
-    * [.getAllSessions(db)](#module_JS API_ database queries.getAllSessions) ⇒
+* [DB API: user configuration queries against the database.](#module_DB API_ user configuration queries against the database.)
+    * [.updateKeyValue(db, sessionId, key, value)](#module_DB API_ user configuration queries against the database..updateKeyValue) ⇒
+    * [.insertOrReplaceClusterState(db, endpointTypeId, clusterRef, side, enabled)](#module_DB API_ user configuration queries against the database..insertOrReplaceClusterState) ⇒
+    * [.insertOrUpdateAttributeState(db, endpointTypeId, id, value, booleanParam)](#module_DB API_ user configuration queries against the database..insertOrUpdateAttributeState)
+    * [.insertOrUpdateCommandState(db, endpointTypeId, id, value, booleanParam)](#module_DB API_ user configuration queries against the database..insertOrUpdateCommandState)
+    * [.insertOrUpdateReportableAttributeState(db, endpointTypeId, id, value, booleanParam)](#module_DB API_ user configuration queries against the database..insertOrUpdateReportableAttributeState)
+    * [.insertEndpoint(db, sessionId, endpointId, endpointTypeRef, networkId)](#module_DB API_ user configuration queries against the database..insertEndpoint) ⇒
+    * [.deleteEndpoint(db, id)](#module_DB API_ user configuration queries against the database..deleteEndpoint) ⇒
+    * [.insertEndpointType(db, sessionId, name, deviceTypeRef)](#module_DB API_ user configuration queries against the database..insertEndpointType) ⇒
+    * [.deleteEndpointType(db, sessionId, id)](#module_DB API_ user configuration queries against the database..deleteEndpointType)
+    * [.updateEndpointType(db, sessionId, endpointTypeId, param, updatedValue)](#module_DB API_ user configuration queries against the database..updateEndpointType)
+    * [.setEndpointDefaults(db, endpointTypeId)](#module_DB API_ user configuration queries against the database..setEndpointDefaults)
+    * [.getAllSesionKeyValues(db, sessionId)](#module_DB API_ user configuration queries against the database..getAllSesionKeyValues) ⇒
+    * [.getAllEndpointTypes(db, sessionId)](#module_DB API_ user configuration queries against the database..getAllEndpointTypes) ⇒
 
-<a name="module_JS API_ database queries.insertDomains"></a>
+<a name="module_DB API_ user configuration queries against the database..updateKeyValue"></a>
 
-### JS API: database queries.insertDomains(db, packageId, data) ⇒
-Inserts domains into the database.
-data is an array of objects that must contain: name
+### DB API: user configuration queries against the database..updateKeyValue(db, sessionId, key, value) ⇒
+Promises to update or insert a key/value pair in SESSION_KEY_VALUE table.
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
-**Returns**: A promise that resolves with an array of rowids of all inserted domains.  
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
+**Returns**: A promise of creating or updating a row, resolves with the rowid of a new row.  
 
 | Param | Type |
 | --- | --- |
 | db | <code>\*</code> | 
-| packageId | <code>\*</code> | 
-| data | <code>\*</code> | 
+| sessionId | <code>\*</code> | 
+| key | <code>\*</code> | 
+| value | <code>\*</code> | 
 
-<a name="module_JS API_ database queries.insertStructs"></a>
+<a name="module_DB API_ user configuration queries against the database..insertOrReplaceClusterState"></a>
 
-### JS API: database queries.insertStructs(db, packageId, data) ⇒
-Inserts structs into the database.
-data is an array of objects that must contain: name
+### DB API: user configuration queries against the database..insertOrReplaceClusterState(db, endpointTypeId, clusterRef, side, enabled) ⇒
+Promises to update the cluster include/exclude state.
+If the entry [as defined uniquely by endpointTypeId, clusterId, side] is not there, then insert
+Else update the entry in place.
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
-**Returns**: A promise that resolves with an array of struct item rowids.  
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
+**Returns**: Promise to update the cluster exclude/include state.  
 
 | Param | Type |
 | --- | --- |
 | db | <code>\*</code> | 
-| packageId | <code>\*</code> | 
-| data | <code>\*</code> | 
-
-<a name="module_JS API_ database queries.insertBitmaps"></a>
-
-### JS API: database queries.insertBitmaps(db, packageId, data) ⇒
-Inserts bitmaps into the database. Data is an array of objects that must contain: name, type
-
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
-**Returns**: A promise of bitmap insertions.  
-
-| Param | Type | Description |
-| --- | --- | --- |
-| db | <code>\*</code> |  |
-| packageId | <code>\*</code> |  |
-| data | <code>\*</code> | Array of object containing 'name' and 'type'. |
+| endpointTypeId | <code>\*</code> | 
+| clusterRef | <code>\*</code> | 
+| side | <code>\*</code> | 
+| enabled | <code>\*</code> | 
 
-<a name="module_JS API_ database queries.deleteSession"></a>
+<a name="module_DB API_ user configuration queries against the database..insertOrUpdateAttributeState"></a>
 
-### JS API: database queries.deleteSession(db, sessionId) ⇒
-Promises to delete a session from the database, including all the rows that have the session as a foreign key.
+### DB API: user configuration queries against the database..insertOrUpdateAttributeState(db, endpointTypeId, id, value, booleanParam)
+Promise to update the attribute state. 
+If the attribute entry [as defined uniquely by endpointTypeId and id], is not there, then create a default entry
+Afterwards, update entry.
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
-**Returns**: A promise of a removal of session.  
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
 
 | Param | Type |
 | --- | --- |
 | db | <code>\*</code> | 
-| sessionId | <code>\*</code> | 
+| endpointTypeId | <code>\*</code> | 
+| id | <code>\*</code> | 
+| value | <code>\*</code> | 
+| booleanParam | <code>\*</code> | 
 
-<a name="module_JS API_ database queries.updateKeyValue"></a>
+<a name="module_DB API_ user configuration queries against the database..insertOrUpdateCommandState"></a>
 
-### JS API: database queries.updateKeyValue(db, sessionId, key, value) ⇒
-Promises to update or insert a key/value pair in SESSION_KEY_VALUE table.
+### DB API: user configuration queries against the database..insertOrUpdateCommandState(db, endpointTypeId, id, value, booleanParam)
+Promise to update the command state. 
+If the attribute entry [as defined uniquely by endpointTypeId and id], is not there, then create a default entry
+Afterwards, update entry.
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
-**Returns**: A promise of creating or updating a row, resolves with the rowid of a new row.  
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
 
 | Param | Type |
 | --- | --- |
 | db | <code>\*</code> | 
-| sessionId | <code>\*</code> | 
-| key | <code>\*</code> | 
+| endpointTypeId | <code>\*</code> | 
+| id | <code>\*</code> | 
 | value | <code>\*</code> | 
+| booleanParam | <code>\*</code> | 
 
-<a name="module_JS API_ database queries.insertOrReplaceClusterState"></a>
+<a name="module_DB API_ user configuration queries against the database..insertOrUpdateReportableAttributeState"></a>
 
-### JS API: database queries.insertOrReplaceClusterState(db, endpointTypeId, clusterId, side, enabled) ⇒
-Promises to update the cluster include/exclude state.
+### DB API: user configuration queries against the database..insertOrUpdateReportableAttributeState(db, endpointTypeId, id, value, booleanParam)
+Promise to update the reportable attribute state. 
+If the reportable attribute entry [as defined uniquely by endpointTypeId and id], is not there, then create a default entry
+Afterwards, update entry.
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
-**Returns**: Promise to update the cluster exclude/include state.  
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
 
 | Param | Type |
 | --- | --- |
 | db | <code>\*</code> | 
 | endpointTypeId | <code>\*</code> | 
-| clusterId | <code>\*</code> | 
-| side | <code>\*</code> | 
-| enabled | <code>\*</code> | 
+| id | <code>\*</code> | 
+| value | <code>\*</code> | 
+| booleanParam | <code>\*</code> | 
 
-<a name="module_JS API_ database queries.insertEndpoint"></a>
+<a name="module_DB API_ user configuration queries against the database..insertEndpoint"></a>
 
-### JS API: database queries.insertEndpoint(db, sessionId, endpointId, endpointTypeRef, networkId) ⇒
+### DB API: user configuration queries against the database..insertEndpoint(db, sessionId, endpointId, endpointTypeRef, networkId) ⇒
 Promises to add an endpoint.
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
 **Returns**: Promise to update endpoints.  
 
 | Param | Type |
@@ -363,12 +400,25 @@ Promises to add an endpoint.
 | endpointTypeRef | <code>\*</code> | 
 | networkId | <code>\*</code> | 
 
-<a name="module_JS API_ database queries.insertEndpointType"></a>
+<a name="module_DB API_ user configuration queries against the database..deleteEndpoint"></a>
+
+### DB API: user configuration queries against the database..deleteEndpoint(db, id) ⇒
+Deletes an endpoint.
+
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
+**Returns**: Promise to delete an endpoint that resolves with the number of rows that were deleted.  
 
-### JS API: database queries.insertEndpointType(db, sessionId, name, deviceTypeRef) ⇒
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| id | <code>\*</code> | 
+
+<a name="module_DB API_ user configuration queries against the database..insertEndpointType"></a>
+
+### DB API: user configuration queries against the database..insertEndpointType(db, sessionId, name, deviceTypeRef) ⇒
 Promises to add an endpoint type.
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
 **Returns**: Promise to update endpoints.  
 
 | Param | Type |
@@ -378,12 +428,52 @@ Promises to add an endpoint type.
 | name | <code>\*</code> | 
 | deviceTypeRef | <code>\*</code> | 
 
-<a name="module_JS API_ database queries.getAllSesionKeyValues"></a>
+<a name="module_DB API_ user configuration queries against the database..deleteEndpointType"></a>
+
+### DB API: user configuration queries against the database..deleteEndpointType(db, sessionId, id)
+Promise to delete an endpoint type.
+
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| sessionId | <code>\*</code> | 
+| id | <code>\*</code> | 
+
+<a name="module_DB API_ user configuration queries against the database..updateEndpointType"></a>
+
+### DB API: user configuration queries against the database..updateEndpointType(db, sessionId, endpointTypeId, param, updatedValue)
+Promise to update a an endpoint type.
+
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| sessionId | <code>\*</code> | 
+| endpointTypeId | <code>\*</code> | 
+| param | <code>\*</code> | 
+| updatedValue | <code>\*</code> | 
+
+<a name="module_DB API_ user configuration queries against the database..setEndpointDefaults"></a>
+
+### DB API: user configuration queries against the database..setEndpointDefaults(db, endpointTypeId)
+Promise to set the default attributes and clusters for a endpoint type.
+
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| endpointTypeId | <code>\*</code> | 
+
+<a name="module_DB API_ user configuration queries against the database..getAllSesionKeyValues"></a>
 
-### JS API: database queries.getAllSesionKeyValues(db, sessionId) ⇒
+### DB API: user configuration queries against the database..getAllSesionKeyValues(db, sessionId) ⇒
 Resolves to an array of objects that contain 'key' and 'value'
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
 **Returns**: Promise to retrieve all session key values.  
 
 | Param | Type |
@@ -391,12 +481,12 @@ Resolves to an array of objects that contain 'key' and 'value'
 | db | <code>\*</code> | 
 | sessionId | <code>\*</code> | 
 
-<a name="module_JS API_ database queries.getAllEndpointTypes"></a>
+<a name="module_DB API_ user configuration queries against the database..getAllEndpointTypes"></a>
 
-### JS API: database queries.getAllEndpointTypes(db, sessionId) ⇒
+### DB API: user configuration queries against the database..getAllEndpointTypes(db, sessionId) ⇒
 Resolves to an array of endpoint types.
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
+**Kind**: static method of [<code>DB API: user configuration queries against the database.</code>](#module_DB API_ user configuration queries against the database.)  
 **Returns**: Promise to retrieve all endpoint types.  
 
 | Param | Type |
@@ -404,18 +494,434 @@ Resolves to an array of endpoint types.
 | db | <code>\*</code> | 
 | sessionId | <code>\*</code> | 
 
-<a name="module_JS API_ database queries.getAllSessions"></a>
+<a name="module_DB API_ generic queries against the database."></a>
+
+## DB API: generic queries against the database.
+This module provides generic queries.
+
+
+* [DB API: generic queries against the database.](#module_DB API_ generic queries against the database.)
+    * [.selectCountFrom(db, table)](#module_DB API_ generic queries against the database..selectCountFrom) ⇒
+    * [.insertFileLocation(db, filePath, category)](#module_DB API_ generic queries against the database..insertFileLocation)
+    * [.selectFileLocation(db, category)](#module_DB API_ generic queries against the database..selectFileLocation)
+
+<a name="module_DB API_ generic queries against the database..selectCountFrom"></a>
+
+### DB API: generic queries against the database..selectCountFrom(db, table) ⇒
+Simple query that returns number of rows in a given table.
+
+**Kind**: static method of [<code>DB API: generic queries against the database.</code>](#module_DB API_ generic queries against the database.)  
+**Returns**: a promise that resolves into the count of the rows in the table.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| table | <code>\*</code> | 
+
+<a name="module_DB API_ generic queries against the database..insertFileLocation"></a>
+
+### DB API: generic queries against the database..insertFileLocation(db, filePath, category)
+Writes the saved location of the file.
+
+**Kind**: static method of [<code>DB API: generic queries against the database.</code>](#module_DB API_ generic queries against the database.)  
 
-### JS API: database queries.getAllSessions(db) ⇒
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| filePath | <code>\*</code> | 
+| category | <code>\*</code> | 
+
+<a name="module_DB API_ generic queries against the database..selectFileLocation"></a>
+
+### DB API: generic queries against the database..selectFileLocation(db, category)
+Retrieves the saved location from a file
+
+**Kind**: static method of [<code>DB API: generic queries against the database.</code>](#module_DB API_ generic queries against the database.)  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| category | <code>\*</code> | 
+
+<a name="module_DB API_ package-based queries."></a>
+
+## DB API: package-based queries.
+This module provides queries related to packages.
+
+
+* [DB API: package-based queries.](#module_DB API_ package-based queries.)
+    * [.forPathCrc(db, path, crcCallback, noneCallback)](#module_DB API_ package-based queries..forPathCrc)
+    * [.getPathCrc(db, path)](#module_DB API_ package-based queries..getPathCrc) ⇒
+    * [.insertPathCrc(db, path, crc)](#module_DB API_ package-based queries..insertPathCrc) ⇒
+    * [.updatePathCrc(db, path, crc)](#module_DB API_ package-based queries..updatePathCrc) ⇒
+
+<a name="module_DB API_ package-based queries..forPathCrc"></a>
+
+### DB API: package-based queries..forPathCrc(db, path, crcCallback, noneCallback)
+Checks if the package with a given path exists and executes appropriate action.
+
+**Kind**: static method of [<code>DB API: package-based queries.</code>](#module_DB API_ package-based queries.)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| db | <code>\*</code> |  |
+| path | <code>\*</code> | Path of a file to check. |
+| crcCallback | <code>\*</code> | This callback is executed if the row exists, with arguments (CRC, PACKAGE_ID) |
+| noneCallback | <code>\*</code> | This callback is executed if the row does not exist. |
+
+<a name="module_DB API_ package-based queries..getPathCrc"></a>
+
+### DB API: package-based queries..getPathCrc(db, path) ⇒
+Resolves with a CRC or null for a given path.
+
+**Kind**: static method of [<code>DB API: package-based queries.</code>](#module_DB API_ package-based queries.)  
+**Returns**: Promise resolving with a CRC or null.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| path | <code>\*</code> | 
+
+<a name="module_DB API_ package-based queries..insertPathCrc"></a>
+
+### DB API: package-based queries..insertPathCrc(db, path, crc) ⇒
+Inserts a given path CRC combination into the table.
+
+**Kind**: static method of [<code>DB API: package-based queries.</code>](#module_DB API_ package-based queries.)  
+**Returns**: Promise of an insertion.  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| db | <code>\*</code> |  |
+| path | <code>\*</code> | Path of the file. |
+| crc | <code>\*</code> | CRC of the file. |
+
+<a name="module_DB API_ package-based queries..updatePathCrc"></a>
+
+### DB API: package-based queries..updatePathCrc(db, path, crc) ⇒
+Updates a CRC in the table.
+
+**Kind**: static method of [<code>DB API: package-based queries.</code>](#module_DB API_ package-based queries.)  
+**Returns**: Promise of an update.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| path | <code>\*</code> | 
+| crc | <code>\*</code> | 
+
+<a name="module_DB API_ session related queries."></a>
+
+## DB API: session related queries.
+This module provides session related queries.
+
+
+* [DB API: session related queries.](#module_DB API_ session related queries.)
+    * [.getAllSessions(db)](#module_DB API_ session related queries..getAllSessions) ⇒
+    * [.setSessionClean(db, sessionId)](#module_DB API_ session related queries..setSessionClean) ⇒
+    * [.getSessionDirtyFlag(db, sessionId)](#module_DB API_ session related queries..getSessionDirtyFlag) ⇒
+    * [.getWindowDirtyFlagWithCallback(db, windowId, fn)](#module_DB API_ session related queries..getWindowDirtyFlagWithCallback)
+    * [.getSessionIdFromWindowdId(db, windowId)](#module_DB API_ session related queries..getSessionIdFromWindowdId) ⇒
+    * [.ensureZapSessionId(db, sessionKey, windowId)](#module_DB API_ session related queries..ensureZapSessionId) ⇒
+    * [.deleteSession(db, sessionId)](#module_DB API_ session related queries..deleteSession) ⇒
+
+<a name="module_DB API_ session related queries..getAllSessions"></a>
+
+### DB API: session related queries..getAllSessions(db) ⇒
 Returns a promise that resolves into an array of objects containing 'sessionId', 'sessionKey' and 'creationTime'.
 
-**Kind**: static method of [<code>JS API: database queries</code>](#module_JS API_ database queries)  
+**Kind**: static method of [<code>DB API: session related queries.</code>](#module_DB API_ session related queries.)  
 **Returns**: A promise of executing a query.  
 
 | Param | Type |
 | --- | --- |
 | db | <code>\*</code> | 
 
+<a name="module_DB API_ session related queries..setSessionClean"></a>
+
+### DB API: session related queries..setSessionClean(db, sessionId) ⇒
+Sets the session dirty flag to false.
+
+**Kind**: static method of [<code>DB API: session related queries.</code>](#module_DB API_ session related queries.)  
+**Returns**: A promise that resolves with the number of rows updated.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| sessionId | <code>\*</code> | 
+
+<a name="module_DB API_ session related queries..getSessionDirtyFlag"></a>
+
+### DB API: session related queries..getSessionDirtyFlag(db, sessionId) ⇒
+Resolves with true or false, depending whether this session is dirty.
+
+**Kind**: static method of [<code>DB API: session related queries.</code>](#module_DB API_ session related queries.)  
+**Returns**: A promise that resolves into true or false, reflecting session dirty state.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| sessionId | <code>\*</code> | 
+
+<a name="module_DB API_ session related queries..getWindowDirtyFlagWithCallback"></a>
+
+### DB API: session related queries..getWindowDirtyFlagWithCallback(db, windowId, fn)
+Executes the query for the dirty flag with a callback, not a promise.
+
+**Kind**: static method of [<code>DB API: session related queries.</code>](#module_DB API_ session related queries.)  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| windowId | <code>\*</code> | 
+| fn | <code>\*</code> | 
+
+<a name="module_DB API_ session related queries..getSessionIdFromWindowdId"></a>
+
+### DB API: session related queries..getSessionIdFromWindowdId(db, windowId) ⇒
+Resolves into a session id, obtained from window id.
+
+**Kind**: static method of [<code>DB API: session related queries.</code>](#module_DB API_ session related queries.)  
+**Returns**: A promise that resolves into an object containing sessionId, sessionKey and creationTime.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| windowId | <code>\*</code> | 
+
+<a name="module_DB API_ session related queries..ensureZapSessionId"></a>
+
+### DB API: session related queries..ensureZapSessionId(db, sessionKey, windowId) ⇒
+Returns a promise that will resolve into a sessionID created from a query.
+
+**Kind**: static method of [<code>DB API: session related queries.</code>](#module_DB API_ session related queries.)  
+**Returns**: promise that resolves into a session id.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| sessionKey | <code>\*</code> | 
+| windowId | <code>\*</code> | 
+
+<a name="module_DB API_ session related queries..deleteSession"></a>
+
+### DB API: session related queries..deleteSession(db, sessionId) ⇒
+Promises to delete a session from the database, including all the rows that have the session as a foreign key.
+
+**Kind**: static method of [<code>DB API: session related queries.</code>](#module_DB API_ session related queries.)  
+**Returns**: A promise of a removal of session.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| sessionId | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access"></a>
+
+## DB API: zcl database access
+This module provides queries for ZCL static queries.
+
+
+* [DB API: zcl database access](#module_DB API_ zcl database access)
+    * [.selectAllEnums(db)](#module_DB API_ zcl database access.selectAllEnums) ⇒
+    * [.selectAllBitmaps(db)](#module_DB API_ zcl database access.selectAllBitmaps) ⇒
+    * [.selectAllDomains(db)](#module_DB API_ zcl database access.selectAllDomains) ⇒
+    * [.selectAllStructs(db)](#module_DB API_ zcl database access.selectAllStructs) ⇒
+    * [.selectAllClusters(db)](#module_DB API_ zcl database access.selectAllClusters) ⇒
+    * [.selectAllDeviceTypes(db)](#module_DB API_ zcl database access.selectAllDeviceTypes) ⇒
+    * [.insertClusters(db, packageId, data)](#module_DB API_ zcl database access.insertClusters) ⇒
+    * [.insertDeviceTypes(db, packageId, data)](#module_DB API_ zcl database access.insertDeviceTypes) ⇒
+    * [.insertDeviceTypeAttributes(db, dtClusterRefDataPairs)](#module_DB API_ zcl database access.insertDeviceTypeAttributes)
+    * [.insertDeviceTypeCommands(db, dtClusterRefDataPairs)](#module_DB API_ zcl database access.insertDeviceTypeCommands)
+    * [.insertDomains(db, packageId, data)](#module_DB API_ zcl database access.insertDomains) ⇒
+    * [.insertStructs(db, packageId, data)](#module_DB API_ zcl database access.insertStructs) ⇒
+    * [.insertEnums(db, packageId, data)](#module_DB API_ zcl database access.insertEnums) ⇒
+    * [.insertBitmaps(db, packageId, data)](#module_DB API_ zcl database access.insertBitmaps) ⇒
+
+<a name="module_DB API_ zcl database access.selectAllEnums"></a>
+
+### DB API: zcl database access.selectAllEnums(db) ⇒
+Retrieves all the enums in the database.
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: Promise that resolves with the rows of enums.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.selectAllBitmaps"></a>
+
+### DB API: zcl database access.selectAllBitmaps(db) ⇒
+Retrieves all the bitmaps in the database.
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: Promise that resolves with the rows of bitmaps.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.selectAllDomains"></a>
+
+### DB API: zcl database access.selectAllDomains(db) ⇒
+Retrieves all the domains in the database.
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: Promise that resolves with the rows of domains.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.selectAllStructs"></a>
+
+### DB API: zcl database access.selectAllStructs(db) ⇒
+Retrieves all the structs in the database.
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: Promise that resolves with the rows of structs.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.selectAllClusters"></a>
+
+### DB API: zcl database access.selectAllClusters(db) ⇒
+Retrieves all the clusters in the database.
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: Promise that resolves with the rows of clusters.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.selectAllDeviceTypes"></a>
+
+### DB API: zcl database access.selectAllDeviceTypes(db) ⇒
+Retrieves all the device types in the database.
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: Promise that resolves with the rows of device types.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.insertClusters"></a>
+
+### DB API: zcl database access.insertClusters(db, packageId, data) ⇒
+Inserts clusters into the database.
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: Promise of cluster insertion.  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| db | <code>\*</code> |  |
+| packageId | <code>\*</code> |  |
+| data | <code>\*</code> | an array of objects that must contain: code, name, description, define. It also contains commands: and attributes: |
+
+<a name="module_DB API_ zcl database access.insertDeviceTypes"></a>
+
+### DB API: zcl database access.insertDeviceTypes(db, packageId, data) ⇒
+Inserts device types into the database.
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: Promise of an insertion of device types.  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| db | <code>\*</code> |  |
+| packageId | <code>\*</code> |  |
+| data | <code>\*</code> | an array of objects that must contain: code, name, description |
+
+<a name="module_DB API_ zcl database access.insertDeviceTypeAttributes"></a>
+
+### DB API: zcl database access.insertDeviceTypeAttributes(db, dtClusterRefDataPairs)
+This handles the loading of device type attribute requirements into the database. 
+There is a need to post-process to attach the actual attribute ref after the fact
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| dtClusterRefDataPairs | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.insertDeviceTypeCommands"></a>
+
+### DB API: zcl database access.insertDeviceTypeCommands(db, dtClusterRefDataPairs)
+This handles the loading of device type command requirements into the database. 
+There is a need to post-process to attach the actual command ref after the fact
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| dtClusterRefDataPairs | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.insertDomains"></a>
+
+### DB API: zcl database access.insertDomains(db, packageId, data) ⇒
+Inserts domains into the database.
+data is an array of objects that must contain: name
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: A promise that resolves with an array of rowids of all inserted domains.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| packageId | <code>\*</code> | 
+| data | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.insertStructs"></a>
+
+### DB API: zcl database access.insertStructs(db, packageId, data) ⇒
+Inserts structs into the database.
+data is an array of objects that must contain: name
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: A promise that resolves with an array of struct item rowids.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| packageId | <code>\*</code> | 
+| data | <code>\*</code> | 
+
+<a name="module_DB API_ zcl database access.insertEnums"></a>
+
+### DB API: zcl database access.insertEnums(db, packageId, data) ⇒
+Inserts enums into the database.
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: A promise of enum insertion.  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| db | <code>\*</code> |  |
+| packageId | <code>\*</code> |  |
+| data | <code>\*</code> | an array of objects that must contain: name, type |
+
+<a name="module_DB API_ zcl database access.insertBitmaps"></a>
+
+### DB API: zcl database access.insertBitmaps(db, packageId, data) ⇒
+Inserts bitmaps into the database. Data is an array of objects that must contain: name, type
+
+**Kind**: static method of [<code>DB API: zcl database access</code>](#module_DB API_ zcl database access)  
+**Returns**: A promise of bitmap insertions.  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| db | <code>\*</code> |  |
+| packageId | <code>\*</code> |  |
+| data | <code>\*</code> | Array of object containing 'name' and 'type'. |
+
 <a name="module_JS API_ generator logic"></a>
 
 ## JS API: generator logic
@@ -609,6 +1115,16 @@ Response JSON:
 ## REST API: generation functions
 This module provides the REST API to the generation.
 
+<a name="module_REST API_ generation functions.registerGenerationApi"></a>
+
+### REST API: generation functions.registerGenerationApi(db, app)
+**Kind**: static method of [<code>REST API: generation functions</code>](#module_REST API_ generation functions)  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| app | <code>\*</code> | 
+
 <a name="module_REST API_ static zcl functions"></a>
 
 ## REST API: static zcl functions
@@ -661,40 +1177,197 @@ Promises to shut down the http server.
 
 **Kind**: static method of [<code>JS API: http server</code>](#module_JS API_ http server)  
 **Returns**: Promise that resolves when server is shut down.  
+<a name="processCommandLineArguments"></a>
+
+## processCommandLineArguments(argv) ⇒
+Process the command line arguments and resets the state in this file
+to the specified values.
+
+**Kind**: global function  
+**Returns**: parsed argv object  
+
+| Param | Type |
+| --- | --- |
+| argv | <code>\*</code> | 
+
+<a name="importDataFromFile"></a>
+
+## importDataFromFile(sessionId, filePath) ⇒
+Take a given session ID and import the data from the file
+
+**Kind**: global function  
+**Returns**: a promise that resolves with the resolution of writing into a database.  
+
+| Param | Type |
+| --- | --- |
+| sessionId | <code>\*</code> | 
+| filePath | <code>\*</code> | 
+
+<a name="writeStateToDatabase"></a>
+
+## writeStateToDatabase(sessionId, state) ⇒
+Given a state object, this method returns a promise that resolves
+with the succesfull writing into the database.
+
+**Kind**: global function  
+**Returns**: a promise that resolves with the sucessful writing  
+
+| Param | Type |
+| --- | --- |
+| sessionId | <code>\*</code> | 
+| state | <code>\*</code> | 
+
+<a name="exportDataIntoFile"></a>
+
+## exportDataIntoFile(db, sessionId, filePath) ⇒
+Toplevel file that takes a given session ID and exports the data into the file
+
+**Kind**: global function  
+**Returns**: A promise that resolves with the path of the file written.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| sessionId | <code>\*</code> | 
+| filePath | <code>\*</code> | 
+
+<a name="createStateFromDatabase"></a>
+
+## createStateFromDatabase(db, sessionId) ⇒
+Given a database and a session id, this method returns a promise that
+resolves with a state object that needs to be saved into a file.
+
+**Kind**: global function  
+**Returns**: state object that needs to be saved into a file.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| sessionId | <code>\*</code> | 
+
+<a name="doOpen"></a>
+
+## doOpen(menuItem, browserWindow, event)
+Perform a file->open operation.
+
+**Kind**: global function  
+
+| Param | Type |
+| --- | --- |
+| menuItem | <code>\*</code> | 
+| browserWindow | <code>\*</code> | 
+| event | <code>\*</code> | 
+
+<a name="doSave"></a>
+
+## doSave(menuItem, browserWindow, event)
+Perform a save, defering to save as if file is not yet selected.
+
+**Kind**: global function  
+
+| Param | Type |
+| --- | --- |
+| menuItem | <code>\*</code> | 
+| browserWindow | <code>\*</code> | 
+| event | <code>\*</code> | 
+
+<a name="doSaveAs"></a>
+
+## doSaveAs(menuItem, browserWindow, event)
+Perform save as.
+
+**Kind**: global function  
+
+| Param | Type |
+| --- | --- |
+| menuItem | <code>\*</code> | 
+| browserWindow | <code>\*</code> | 
+| event | <code>\*</code> | 
+
 <a name="generateInDir"></a>
 
-## generateInDir()
-Given: Browser Window
-Returns: N/A
-Description: This function gets the directory where user wants the output and
+## generateInDir(browserWindow)
+This function gets the directory where user wants the output and
 calls generateCode function which generates the code in the user selected
 output.
 
 **Kind**: global function  
+
+| Param | Type |
+| --- | --- |
+| browserWindow | <code>\*</code> | 
+
 <a name="setHandlebarTemplateDirectory"></a>
 
-## setHandlebarTemplateDirectory()
-Given: Browser Window
-Returns: N/A
-Description: This function gets the directory where user wants the output and
-calls generateCode function which generates the code in the user selected
-output.
+## setHandlebarTemplateDirectory(browserWindow)
+This function gets the directory where user wants the output and calls 
+generateCode function which generates the code in the user selected output.
 
 **Kind**: global function  
+
+| Param | Type |
+| --- | --- |
+| browserWindow | <code>\*</code> | 
+
 <a name="generateCode"></a>
 
-## generateCode()
-Given: N/A
-Returns: N/A
-Description: This function generates the code into the user defined directory using promises
+## generateCode(db)
+This function generates the code into the user defined directory using promises
+
+**Kind**: global function  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+
+<a name="fileSave"></a>
+
+## fileSave(db, winId, filePath) ⇒
+perform the save.
+
+**Kind**: global function  
+**Returns**: Promise of saving.  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| winId | <code>\*</code> | 
+| filePath | <code>\*</code> | 
+
+<a name="fileOpen"></a>
+
+## fileOpen(db, winId, filePaths)
+Perform the do open action.
 
 **Kind**: global function  
+
+| Param | Type |
+| --- | --- |
+| db | <code>\*</code> | 
+| winId | <code>\*</code> | 
+| filePaths | <code>\*</code> | 
+
 <a name="resolveGenerationDirectory"></a>
 
-## resolveGenerationDirectory()
-Given: a map and a generation directory path.
-Return: a map which has the generation directory.
+## resolveGenerationDirectory(map) ⇒
 Description: Resolve the generation directory to be able to generate to the
 correct directory.
 
 **Kind**: global function  
+**Returns**: promise that resolves into a map.  
+
+| Param | Type |
+| --- | --- |
+| map | <code>\*</code> | 
+
+<a name="initMenu"></a>
+
+## initMenu(port)
+Initialize a menu.
+
+**Kind**: global function  
+
+| Param | Type |
+| --- | --- |
+| port | <code>\*</code> | 
+
diff --git a/docs/design.md b/docs/design.md
index 06e3f768..ef232d4d 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -2,7 +2,7 @@
 
 The ZAP project delivers a ZCL configuration via an "advanced configurator" and a generator platform.
 
-- [Zigbe Advanced Platform](#zigbe-advanced-platform)
+- [Zigbee Advanced Platform (ZAP)](#zigbee-advanced-platform-zap)
   - [Use cases](#use-cases)
     - [Standalone electron application](#standalone-electron-application)
     - [Command line regeneration](#command-line-regeneration)
@@ -16,6 +16,9 @@ The ZAP project delivers a ZCL configuration via an "advanced configurator" and
     - [Schema design principles](#schema-design-principles)
     - [Schema diagram](#schema-diagram)
   - [Embedded code](#embedded-code)
+    - [Database](#database)
+    - [Metalayer](#metalayer)
+    - [Zap API](#zap-api)
   - [Versioning and backwards compatibility](#versioning-and-backwards-compatibility)
     - [Compatibility considerations](#compatibility-considerations)
     - [Dealing with the generation variant](#dealing-with-the-generation-variant)
@@ -137,22 +140,48 @@ _Developer note_: If there are any changes to the SQL script, the picture should
 
 ## Embedded code
 
-Following is the laundry-list of changes in the embedded code:
+### Database 
 
-* Rethink and reengineer entire ZCL embedded layers as a "addon library", that interfaces with lower layers via a well-defined API, instead of direct calls into the stack APIs wherever needed.
+We need to develop a common database layer that will be used across both Thread, CHIP and Zigbee or any other underlying platform. We should investigate both current options and come up with the best solution for both.
 
-* Develop the API for the Zigbee stack.
+The database needs to support:
 
-* Develop the same API for the pure-simulation environment, which allows ZCL library to run in Posix environment, possibly on top of java simulator.
+- **singleton attributes**: the attributes that have same value across multiple endpoints.
+- **flash-saved attributes**: the attributes whose value is saved to flash for persistence across resets.
+- **external attributes**: the attributes whose value is not stored anywhere, but whenever the code queries them, the value is received or stored via a customer callback.
+- **manufacturer-specific attributes and commands**
+- **external APIs**: that might allow other data tokens to be stored into this database for any purpose customers might come up with
 
-* Abandon current mechanism of parsing OTA content and issuing callbacks for it, and replace it with a struct-driven event-bus approach.
+The database design should be ZCL-independent, but should be developed as just-a-database, useful for storing anything. ZCL is a special case that uses this database. It should build into a library that should also compile on POSIX and be fully unit-testable on a Linux box.
+It is also possible to reuse an existing embedded database for this purpose.
 
-* Threads? (Discuss. TBD.)
+The access to the database should be done with a well defined API, so the rest of the ZCL application layer should be able to the transplanted from one to another databse. In a case of a desktop-application (for unit testing, for example), and use on Android devices, using sqlite database might make a lot of sense.
+The APIs should be cleanly separated, so that migrating application layer from embedded database onto a sqlite file should be possible.
 
-* Develop a clean API that allows from-the-top extensions, which are essentially customer callbacks to the ZCL command/attribute logic and ability to contribute custom commands and attributes from the top. (Either based on source-code approach or library add-ons.)
+### Metalayer
 
-* Rework the attribute storage logic: develop a reusable embedded database which covers all the features ZCL offering needs, while being an independent UP component, that can be used by any other part of the SDK as well. For example, BLE characteristics could use same database.
+The metalayer is the struct/spec layer that was created for Thread. In zigbee, there is no concept of a "command struct". Commands are parsed from a packet payload and then passed around as long list of function arguments, which is unwieldy and confusing. For Thread, Richard created a layer where each command from XML files, is generated into a struct that will be populated by the code and the spec which is a chunk of metadata used to populate the struct. Once the struct is created, a pointer to this data is passed around the functions as a single pointer, which is much more handy. We should create a single metalayer, probably copying the Thread model, and then retrofit Zigbee code with it.
 
+Zigbee metalayer should be a library, built and fully unit-testable on a Linux environment.
+
+### Zap API
+
+Zap implements the clusters in a form of "plugins". Each cluster server or client implementation will typically be a separate plugin.
+In order for these plugins to me interchangeably used on top of any transport layer or underlying stack implementation, the code in them is NOT allowed to use any underlying stack or RTOS APIs. 
+They are only allowed to use the Zap API, which will be defined for this purpose.
+
+There will be multiple actual implementations of Zap API:
+- **mock implementation**: pure stubs, do nothing, just allows a compile to succeed without any underlying layers.
+- **Silabs Zigbee implementation**: implementation that binds the zap library with the Silicon Labs Zigbee Pro stack.
+- **Posix implementation**: POSIX based C code implementation, used in enhanced unit tests and simulation runs.
+- **CHIP implementation**: Implementation of the API on top of CHIP OpenWeave stack.
+
+Zap API will provide functions in roughly following categories:
+- **network abstraction layer**: abstractions for basic interaction with sending and receiving packets
+- **payload codecs**: abstractions for encoding and decoding payload into the ZCL structures.
+- **OS abstraction layer**: abstractions for any kind of RTOS or lower level services, such as event management, memory allocation, etc., required by the plugin code.
+- **DB abstraction layer**: abstractions to access embedded attribute database for storage of ZCL attributes or other tokens. 
+  
 ## Versioning and backwards compatibility
 
 Zap infrastructure needs to be able to deal with the use case, where a user has multiple ZCL data packs installed and at the same time, the user may have multiple projects (either in IDE, or outside of it) opened simultaneously against one or more ZCL data packs.
diff --git a/docs/zap-schema.svg b/docs/zap-schema.svg
index a1507dd1..aa21494c 100644
--- a/docs/zap-schema.svg
+++ b/docs/zap-schema.svg
@@ -4,15 +4,15 @@
 <!-- Generated by graphviz version 2.40.1 (0)
  -->
 <!-- Title: SchemaCrawler_Diagram Pages: 1 -->
-<svg width="1356pt" height="1384pt"
- viewBox="0.00 0.00 1356.00 1384.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<svg width="1467pt" height="1384pt"
+ viewBox="0.00 0.00 1467.00 1384.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1380)">
 <title>SchemaCrawler_Diagram</title>
-<polygon fill="#ffffff" stroke="transparent" points="1024,-4 1024,-44 1340,-44 1340,-4 1024,-4"/>
-<text text-anchor="start" x="1050" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">generated by</text>
-<text text-anchor="start" x="1151" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SchemaCrawler 16.4.1</text>
-<text text-anchor="start" x="1027" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SQL schema is copyrighted by Silicon Labs.</text>
-<polygon fill="none" stroke="#888888" points="1024,-4 1024,-44 1340,-44 1340,-4 1024,-4"/>
+<polygon fill="#ffffff" stroke="transparent" points="1135,-4 1135,-44 1451,-44 1451,-4 1135,-4"/>
+<text text-anchor="start" x="1161" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">generated by</text>
+<text text-anchor="start" x="1262" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SchemaCrawler 16.4.1</text>
+<text text-anchor="start" x="1138" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SQL schema is copyrighted by Silicon Labs.</text>
+<polygon fill="none" stroke="#888888" points="1135,-4 1135,-44 1451,-44 1451,-4 1135,-4"/>
 <!-- attribute_a6e02edb -->
 <g id="node1" class="node">
 <title>attribute_a6e02edb</title>
@@ -65,7 +65,7 @@
 <polygon fill="none" stroke="#888888" points="674,-412.5 674,-699.5 988,-699.5 988,-412.5 674,-412.5"/>
 </g>
 <!-- cluster_5ec71239 -->
-<g id="node4" class="node">
+<g id="node6" class="node">
 <title>cluster_5ec71239</title>
 <polygon fill="#ffffff" stroke="transparent" points="308,-507.5 308,-680.5 622,-680.5 622,-507.5 308,-507.5"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="309,-660 309,-679 488,-679 488,-660 309,-660"/>
@@ -98,7 +98,7 @@
 <polygon fill="none" stroke="#888888" points="308,-507.5 308,-680.5 622,-680.5 622,-507.5 308,-507.5"/>
 </g>
 <!-- attribute_a6e02edb&#45;&gt;cluster_5ec71239 -->
-<g id="edge2" class="edge">
+<g id="edge4" class="edge">
 <title>attribute_a6e02edb:w&#45;&gt;cluster_5ec71239:e</title>
 <path fill="none" stroke="#000000" d="M657.0754,-636.0294C648.1312,-640.4302 641.9789,-647.207 630.9927,-649.8701"/>
 <polygon fill="#000000" stroke="#000000" points="665.2435,-634.1933 675.987,-636.3904 670.1217,-633.0966 675,-632 675,-632 675,-632 670.1217,-633.0966 674.013,-627.6096 665.2435,-634.1933 665.2435,-634.1933"/>
@@ -108,8 +108,138 @@
 <polygon fill="#000000" stroke="#000000" points="627.5238,-655.2942 626.4002,-645.3575 628.3875,-645.1328 629.5112,-655.0694 627.5238,-655.2942"/>
 <polyline fill="none" stroke="#000000" points="625.9683,-650.4382 630.9367,-649.8764 "/>
 </g>
-<!-- bitmap_74cc598e -->
+<!-- endpoint_type_attribute_c265400 -->
 <g id="node2" class="node">
+<title>endpoint_type_attribute_c265400</title>
+<polygon fill="#ffffff" stroke="transparent" points="1095.5,-767.5 1095.5,-940.5 1395.5,-940.5 1395.5,-767.5 1095.5,-767.5"/>
+<polygon fill="#f2e9ce" stroke="transparent" points="1096.5,-920 1096.5,-939 1326.5,-939 1326.5,-920 1096.5,-920"/>
+<text text-anchor="start" x="1098.5" y="-926.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_TYPE_ATTRIBUTE</text>
+<polygon fill="#f2e9ce" stroke="transparent" points="1326.5,-920 1326.5,-939 1394.5,-939 1394.5,-920 1326.5,-920"/>
+<text text-anchor="start" x="1345.5" y="-925.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
+<text text-anchor="start" x="1098.5" y="-906.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENDPOINT_TYPE_REF</text>
+<text text-anchor="start" x="1286.5" y="-906.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-906.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-887.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ATTRIBUTE_REF</text>
+<text text-anchor="start" x="1286.5" y="-887.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-887.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-868.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INCLUDED</text>
+<text text-anchor="start" x="1286.5" y="-868.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-868.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-849.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">&quot;EXTERNAL&quot;</text>
+<text text-anchor="start" x="1286.5" y="-849.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-849.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-830.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">FLASH</text>
+<text text-anchor="start" x="1286.5" y="-830.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-830.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-811.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SINGLETON</text>
+<text text-anchor="start" x="1286.5" y="-811.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-811.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-792.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">BOUNDED</text>
+<text text-anchor="start" x="1286.5" y="-792.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-792.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-773.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">DEFAULT_VALUE</text>
+<text text-anchor="start" x="1286.5" y="-773.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-773.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
+<polygon fill="none" stroke="#888888" points="1095.5,-767.5 1095.5,-940.5 1395.5,-940.5 1395.5,-767.5 1095.5,-767.5"/>
+</g>
+<!-- endpoint_type_attribute_c265400&#45;&gt;attribute_a6e02edb -->
+<g id="edge1" class="edge">
+<title>endpoint_type_attribute_c265400:w&#45;&gt;attribute_a6e02edb:e</title>
+<path fill="none" stroke="#000000" d="M1085.5761,-877.434C1062.3478,-834.6044 1014.0013,-710.0641 994.002,-677.7385"/>
+<polygon fill="#000000" stroke="#000000" points="1090.5002,-883.9998 1092.8999,-894.6999 1093.5001,-887.9999 1096.5,-892 1096.5,-892 1096.5,-892 1093.5001,-887.9999 1100.1001,-889.3001 1090.5002,-883.9998 1090.5002,-883.9998"/>
+<ellipse fill="none" stroke="#000000" cx="1088.1003" cy="-880.7998" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="983.9634,-674.0962 991.3785,-667.3868 992.7204,-668.8698 985.3053,-675.5793 983.9634,-674.0962"/>
+<polyline fill="none" stroke="#000000" points="987,-670 990.3547,-673.7076 "/>
+<polygon fill="#000000" stroke="#000000" points="987.3181,-677.8038 994.7332,-671.0944 996.0751,-672.5774 988.66,-679.2868 987.3181,-677.8038"/>
+<polyline fill="none" stroke="#000000" points="990.3547,-673.7076 993.7094,-677.4151 "/>
+</g>
+<!-- endpoint_type_9857dc03 -->
+<g id="node13" class="node">
+<title>endpoint_type_9857dc03</title>
+<polygon fill="#ffffff" stroke="transparent" points="678.5,-906 678.5,-1022 983.5,-1022 983.5,-906 678.5,-906"/>
+<polygon fill="#f2e9ce" stroke="transparent" points="680,-1002 680,-1021 850,-1021 850,-1002 680,-1002"/>
+<text text-anchor="start" x="682" y="-1008.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_TYPE</text>
+<polygon fill="#f2e9ce" stroke="transparent" points="850,-1002 850,-1021 983,-1021 983,-1002 850,-1002"/>
+<text text-anchor="start" x="934" y="-1007.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
+<text text-anchor="start" x="682" y="-989.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_TYPE_ID</text>
+<text text-anchor="start" x="843" y="-988.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="852" y="-988.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="843" y="-969.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="852" y="-969.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">auto&#45;incremented</text>
+<text text-anchor="start" x="682" y="-950.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SESSION_REF</text>
+<text text-anchor="start" x="843" y="-950.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="852" y="-950.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="682" y="-931.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">NAME</text>
+<text text-anchor="start" x="843" y="-931.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="852" y="-931.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
+<text text-anchor="start" x="682" y="-912.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">DEVICE_TYPE_REF</text>
+<text text-anchor="start" x="843" y="-912.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="852" y="-912.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<polygon fill="none" stroke="#888888" points="678.5,-906 678.5,-1022 983.5,-1022 983.5,-906 678.5,-906"/>
+</g>
+<!-- endpoint_type_attribute_c265400&#45;&gt;endpoint_type_9857dc03 -->
+<g id="edge13" class="edge">
+<title>endpoint_type_attribute_c265400:w&#45;&gt;endpoint_type_9857dc03:e</title>
+<path fill="none" stroke="#000000" d="M1078.4584,-913.7944C1059.9742,-920.4693 1053.9647,-937.981 1032,-954 1012.6741,-968.0945 1010.9327,-986.7666 993.1599,-991.7394"/>
+<polygon fill="#000000" stroke="#000000" points="1086.6178,-912.5306 1097.1888,-915.447 1091.5589,-911.7653 1096.5,-911 1096.5,-911 1096.5,-911 1091.5589,-911.7653 1095.8112,-906.553 1086.6178,-912.5306 1086.6178,-912.5306"/>
+<ellipse fill="none" stroke="#000000" cx="1082.665" cy="-913.1429" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="984.6081,-997.8388 983.3767,-987.9149 985.3615,-987.6686 986.5929,-997.5925 984.6081,-997.8388"/>
+<polyline fill="none" stroke="#000000" points="983,-993 987.962,-992.3843 "/>
+<polygon fill="#000000" stroke="#000000" points="989.5701,-997.2231 988.3386,-987.2992 990.3234,-987.0529 991.5548,-996.9768 989.5701,-997.2231"/>
+<polyline fill="none" stroke="#000000" points="987.962,-992.3843 992.9239,-991.7686 "/>
+</g>
+<!-- endpoint_type_reportable_attribute_bba50e25 -->
+<g id="node3" class="node">
+<title>endpoint_type_reportable_attribute_bba50e25</title>
+<polygon fill="#ffffff" stroke="transparent" points="1040,-606.5 1040,-741.5 1451,-741.5 1451,-606.5 1040,-606.5"/>
+<polygon fill="#f2e9ce" stroke="transparent" points="1041.5,-721 1041.5,-740 1382.5,-740 1382.5,-721 1041.5,-721"/>
+<text text-anchor="start" x="1043.5" y="-727.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_TYPE_REPORTABLE_ATTRIBUTE</text>
+<polygon fill="#f2e9ce" stroke="transparent" points="1382.5,-721 1382.5,-740 1450.5,-740 1450.5,-721 1382.5,-721"/>
+<text text-anchor="start" x="1401.5" y="-726.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
+<text text-anchor="start" x="1043.5" y="-707.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENDPOINT_TYPE_REF</text>
+<text text-anchor="start" x="1291.5" y="-707.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1384.5" y="-707.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1043.5" y="-688.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ATTRIBUTE_REF</text>
+<text text-anchor="start" x="1291.5" y="-688.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1384.5" y="-688.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1043.5" y="-669.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INCLUDED</text>
+<text text-anchor="start" x="1291.5" y="-669.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1384.5" y="-669.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1043.5" y="-650.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">MIN_INTERVAL</text>
+<text text-anchor="start" x="1291.5" y="-650.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1384.5" y="-650.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1043.5" y="-631.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">MAX_INTERVAL</text>
+<text text-anchor="start" x="1291.5" y="-631.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1384.5" y="-631.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1043.5" y="-612.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">REPORTABLE_CHANGE</text>
+<text text-anchor="start" x="1291.5" y="-612.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1384.5" y="-612.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<polygon fill="none" stroke="#888888" points="1040,-606.5 1040,-741.5 1451,-741.5 1451,-606.5 1040,-606.5"/>
+</g>
+<!-- endpoint_type_reportable_attribute_bba50e25&#45;&gt;attribute_a6e02edb -->
+<g id="edge2" class="edge">
+<title>endpoint_type_reportable_attribute_bba50e25:w&#45;&gt;attribute_a6e02edb:e</title>
+<path fill="none" stroke="#000000" d="M1024.0164,-688.5654C1014.6019,-683.2394 1008.6855,-674.6125 997.1083,-671.3276"/>
+<polygon fill="#000000" stroke="#000000" points="1031.8069,-690.5414 1040.3936,-697.3619 1036.6535,-691.7707 1041.5,-693 1041.5,-693 1041.5,-693 1036.6535,-691.7707 1042.6064,-688.6381 1031.8069,-690.5414 1031.8069,-690.5414"/>
+<ellipse fill="none" stroke="#000000" cx="1027.9297" cy="-689.5579" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="987.3404,-675.0877 988.6426,-665.1728 990.6256,-665.4333 989.3233,-675.3481 987.3404,-675.0877"/>
+<polyline fill="none" stroke="#000000" points="987,-670 991.9574,-670.6511 "/>
+<polygon fill="#000000" stroke="#000000" points="992.2978,-675.7388 993.6,-665.8239 995.583,-666.0844 994.2808,-675.9992 992.2978,-675.7388"/>
+<polyline fill="none" stroke="#000000" points="991.9574,-670.6511 996.9149,-671.3023 "/>
+</g>
+<!-- endpoint_type_reportable_attribute_bba50e25&#45;&gt;endpoint_type_9857dc03 -->
+<g id="edge16" class="edge">
+<title>endpoint_type_reportable_attribute_bba50e25:w&#45;&gt;endpoint_type_9857dc03:e</title>
+<path fill="none" stroke="#000000" d="M1023.6502,-714.3449C936.8312,-740.5566 1093.684,-977.9707 993.1804,-992.3214"/>
+<polygon fill="#000000" stroke="#000000" points="1031.5852,-713.3025 1042.0861,-716.4617 1036.5426,-712.6513 1041.5,-712 1041.5,-712 1041.5,-712 1036.5426,-712.6513 1040.9139,-707.5383 1031.5852,-713.3025 1031.5852,-713.3025"/>
+<ellipse fill="none" stroke="#000000" cx="1027.6193" cy="-713.8235" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="984.3304,-997.9224 983.6652,-987.9446 985.6608,-987.8115 986.326,-997.7894 984.3304,-997.9224"/>
+<polyline fill="none" stroke="#000000" points="983,-993 987.9889,-992.6674 "/>
+<polygon fill="#000000" stroke="#000000" points="989.3193,-997.5898 988.6541,-987.6119 990.6497,-987.4789 991.3149,-997.4568 989.3193,-997.5898"/>
+<polyline fill="none" stroke="#000000" points="987.9889,-992.6674 992.9779,-992.3348 "/>
+</g>
+<!-- bitmap_74cc598e -->
+<g id="node4" class="node">
 <title>bitmap_74cc598e</title>
 <polygon fill="#ffffff" stroke="transparent" points="341,-1121 341,-1237 589,-1237 589,-1121 341,-1121"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="342,-1217 342,-1236 455,-1236 455,-1217 342,-1217"/>
@@ -133,7 +263,7 @@
 <polygon fill="none" stroke="#888888" points="341,-1121 341,-1237 589,-1237 589,-1121 341,-1121"/>
 </g>
 <!-- package_fab13485 -->
-<g id="node15" class="node">
+<g id="node18" class="node">
 <title>package_fab13485</title>
 <polygon fill="#ffffff" stroke="transparent" points="8,-654.5 8,-751.5 256,-751.5 256,-654.5 8,-654.5"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="9,-731 9,-750 122,-750 122,-731 9,-731"/>
@@ -154,18 +284,18 @@
 <polygon fill="none" stroke="#888888" points="8,-654.5 8,-751.5 256,-751.5 256,-654.5 8,-654.5"/>
 </g>
 <!-- bitmap_74cc598e&#45;&gt;package_fab13485 -->
-<g id="edge12" class="edge">
+<g id="edge18" class="edge">
 <title>bitmap_74cc598e:w&#45;&gt;package_fab13485:e</title>
-<path fill="none" stroke="#000000" d="M324.4438,-1164.8493C306.697,-1154.1444 309.455,-1124.4438 300,-1096 274.7291,-1019.9765 333.2836,-746.9168 264.9855,-723.5911"/>
-<polygon fill="#000000" stroke="#000000" points="332.2683,-1166.6992 340.9646,-1173.3793 337.1341,-1167.8496 342,-1169 342,-1169 342,-1169 337.1341,-1167.8496 343.0354,-1164.6207 332.2683,-1166.6992 332.2683,-1166.6992"/>
-<ellipse fill="none" stroke="#000000" cx="328.3756" cy="-1165.7788" rx="4" ry="4"/>
-<polygon fill="#000000" stroke="#000000" points="255.2007,-727.0951 256.7744,-717.2197 258.7495,-717.5344 257.1758,-727.4098 255.2007,-727.0951"/>
-<polyline fill="none" stroke="#000000" points="255,-722 259.9377,-722.7868 "/>
-<polygon fill="#000000" stroke="#000000" points="260.1384,-727.8819 261.7121,-718.0065 263.6872,-718.3212 262.1135,-728.1966 260.1384,-727.8819"/>
-<polyline fill="none" stroke="#000000" points="259.9377,-722.7868 264.8754,-723.5737 "/>
+<path fill="none" stroke="#000000" d="M324.3323,-1164.759C306.9608,-1154.0907 309.3915,-1124.9878 300,-1097 274.4466,-1020.8482 333.4614,-746.9899 265.01,-723.5958"/>
+<polygon fill="#000000" stroke="#000000" points="332.2762,-1166.6659 340.9496,-1173.3757 337.1381,-1167.8329 342,-1169 342,-1169 342,-1169 337.1381,-1167.8329 343.0504,-1164.6243 332.2762,-1166.6659 332.2762,-1166.6659"/>
+<ellipse fill="none" stroke="#000000" cx="328.3867" cy="-1165.7322" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="255.2003,-727.0951 256.7747,-717.2198 258.7498,-717.5347 257.1754,-727.41 255.2003,-727.0951"/>
+<polyline fill="none" stroke="#000000" points="255,-722 259.9376,-722.7872 "/>
+<polygon fill="#000000" stroke="#000000" points="260.138,-727.8823 261.7124,-718.007 263.6874,-718.3219 262.113,-728.1972 260.138,-727.8823"/>
+<polyline fill="none" stroke="#000000" points="259.9376,-722.7872 264.8753,-723.5744 "/>
 </g>
 <!-- bitmap_field_bfea8629 -->
-<g id="node3" class="node">
+<g id="node5" class="node">
 <title>bitmap_field_bfea8629</title>
 <polygon fill="#ffffff" stroke="transparent" points="736.5,-1190 736.5,-1268 925.5,-1268 925.5,-1190 736.5,-1190"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="738,-1248 738,-1267 857,-1267 857,-1248 738,-1248"/>
@@ -184,7 +314,7 @@
 <polygon fill="none" stroke="#888888" points="736.5,-1190 736.5,-1268 925.5,-1268 925.5,-1190 736.5,-1190"/>
 </g>
 <!-- bitmap_field_bfea8629&#45;&gt;bitmap_74cc598e -->
-<g id="edge1" class="edge">
+<g id="edge3" class="edge">
 <title>bitmap_field_bfea8629:w&#45;&gt;bitmap_74cc598e:e</title>
 <path fill="none" stroke="#000000" d="M719.8498,-1238.2026C669.7831,-1233.6252 651.6258,-1210.806 598.0483,-1208.2357"/>
 <polygon fill="#000000" stroke="#000000" points="728.0096,-1238.561 737.8025,-1243.4957 733.0048,-1238.7805 738,-1239 738,-1239 738,-1239 733.0048,-1238.7805 738.1975,-1234.5043 728.0096,-1238.561 728.0096,-1238.561"/>
@@ -195,7 +325,7 @@
 <polyline fill="none" stroke="#000000" points="592.9986,-1208.1173 597.9973,-1208.2346 "/>
 </g>
 <!-- cluster_5ec71239&#45;&gt;package_fab13485 -->
-<g id="edge13" class="edge">
+<g id="edge19" class="edge">
 <title>cluster_5ec71239:w&#45;&gt;package_fab13485:e</title>
 <path fill="none" stroke="#000000" d="M291.6852,-619.1726C270.3303,-640.2493 296.006,-708.7085 265.2555,-720.3193"/>
 <polygon fill="#000000" stroke="#000000" points="299.5806,-616.358 310.5111,-617.2387 304.2903,-614.679 309,-613 309,-613 309,-613 304.2903,-614.679 307.4889,-608.7613 299.5806,-616.358 299.5806,-616.358"/>
@@ -206,7 +336,7 @@
 <polyline fill="none" stroke="#000000" points="259.9342,-721.1913 264.8684,-720.3826 "/>
 </g>
 <!-- command_6371df8a -->
-<g id="node5" class="node">
+<g id="node7" class="node">
 <title>command_6371df8a</title>
 <polygon fill="#ffffff" stroke="transparent" points="674,-156 674,-348 988,-348 988,-156 674,-156"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="675,-328 675,-347 854,-347 854,-328 675,-328"/>
@@ -242,7 +372,7 @@
 <polygon fill="none" stroke="#888888" points="674,-156 674,-348 988,-348 988,-156 674,-156"/>
 </g>
 <!-- command_6371df8a&#45;&gt;cluster_5ec71239 -->
-<g id="edge3" class="edge">
+<g id="edge5" class="edge">
 <title>command_6371df8a:w&#45;&gt;cluster_5ec71239:e</title>
 <path fill="none" stroke="#000000" d="M658.2779,-288.0609C611.4045,-336.7157 688.984,-621.1735 631.0316,-648.8366"/>
 <polygon fill="#000000" stroke="#000000" points="665.7876,-284.8899 676.7505,-285.1456 670.3938,-282.945 675,-281 675,-281 675,-281 670.3938,-282.945 673.2495,-276.8544 665.7876,-284.8899 665.7876,-284.8899"/>
@@ -253,7 +383,7 @@
 <polyline fill="none" stroke="#000000" points="625.8876,-649.9459 630.7753,-648.8918 "/>
 </g>
 <!-- device_type_cluster_7298b97d -->
-<g id="node6" class="node">
+<g id="node8" class="node">
 <title>device_type_cluster_7298b97d</title>
 <polygon fill="#ffffff" stroke="transparent" points="701.5,-726 701.5,-880 960.5,-880 960.5,-726 701.5,-726"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="703,-860 703,-879 892,-879 892,-860 703,-860"/>
@@ -284,7 +414,7 @@
 <polygon fill="none" stroke="#888888" points="701.5,-726 701.5,-880 960.5,-880 960.5,-726 701.5,-726"/>
 </g>
 <!-- device_type_cluster_7298b97d&#45;&gt;cluster_5ec71239 -->
-<g id="edge4" class="edge">
+<g id="edge6" class="edge">
 <title>device_type_cluster_7298b97d:w&#45;&gt;cluster_5ec71239:e</title>
 <path fill="none" stroke="#000000" d="M685.1153,-828.7039C631.2033,-805.2744 695.8948,-664.502 631.0373,-651.9017"/>
 <polygon fill="#000000" stroke="#000000" points="693.1656,-830.1875 702.1844,-836.4255 698.0828,-831.0938 703,-832 703,-832 703,-832 698.0828,-831.0938 703.8156,-827.5745 693.1656,-830.1875 693.1656,-830.1875"/>
@@ -295,7 +425,7 @@
 <polyline fill="none" stroke="#000000" points="625.9799,-651.4474 630.9599,-651.8949 "/>
 </g>
 <!-- device_type_2620a7e2 -->
-<g id="node9" class="node">
+<g id="node12" class="node">
 <title>device_type_2620a7e2</title>
 <polygon fill="#ffffff" stroke="transparent" points="325,-726 325,-880 605,-880 605,-726 325,-726"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="326,-860 326,-879 471,-879 471,-860 326,-860"/>
@@ -325,7 +455,7 @@
 <polygon fill="none" stroke="#888888" points="325,-726 325,-880 605,-880 605,-726 325,-726"/>
 </g>
 <!-- device_type_cluster_7298b97d&#45;&gt;device_type_2620a7e2 -->
-<g id="edge7" class="edge">
+<g id="edge10" class="edge">
 <title>device_type_cluster_7298b97d:w&#45;&gt;device_type_2620a7e2:e</title>
 <path fill="none" stroke="#000000" d="M684.9549,-851C657.8193,-851 644.1076,-851 614.2859,-851"/>
 <polygon fill="#000000" stroke="#000000" points="693,-851.0001 703,-855.5 698,-851 703,-851 703,-851 703,-851 698,-851 703,-846.5 693,-851.0001 693,-851.0001"/>
@@ -336,108 +466,128 @@
 <polyline fill="none" stroke="#000000" points="609,-851 614,-851.0001 "/>
 </g>
 <!-- endpoint_type_cluster_c12e3c9e -->
-<g id="node7" class="node">
+<g id="node9" class="node">
 <title>endpoint_type_cluster_c12e3c9e</title>
-<polygon fill="#ffffff" stroke="transparent" points="1048,-619.5 1048,-716.5 1332,-716.5 1332,-619.5 1048,-619.5"/>
-<polygon fill="#f2e9ce" stroke="transparent" points="1049,-696 1049,-715 1263,-715 1263,-696 1049,-696"/>
-<text text-anchor="start" x="1051" y="-702.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_TYPE_CLUSTER</text>
-<polygon fill="#f2e9ce" stroke="transparent" points="1263,-696 1263,-715 1331,-715 1331,-696 1263,-696"/>
-<text text-anchor="start" x="1282" y="-701.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
-<text text-anchor="start" x="1051" y="-682.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENDPOINT_TYPE_REF</text>
-<text text-anchor="start" x="1231" y="-682.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1265" y="-682.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<text text-anchor="start" x="1051" y="-663.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">CLUSTER_REF</text>
-<text text-anchor="start" x="1231" y="-663.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1265" y="-663.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<text text-anchor="start" x="1051" y="-644.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SIDE</text>
-<text text-anchor="start" x="1231" y="-644.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1265" y="-644.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
-<text text-anchor="start" x="1051" y="-625.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENABLED</text>
-<text text-anchor="start" x="1231" y="-625.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1265" y="-625.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<polygon fill="none" stroke="#888888" points="1048,-619.5 1048,-716.5 1332,-716.5 1332,-619.5 1048,-619.5"/>
+<polygon fill="#ffffff" stroke="transparent" points="1103.5,-483.5 1103.5,-580.5 1387.5,-580.5 1387.5,-483.5 1103.5,-483.5"/>
+<polygon fill="#f2e9ce" stroke="transparent" points="1104.5,-560 1104.5,-579 1318.5,-579 1318.5,-560 1104.5,-560"/>
+<text text-anchor="start" x="1106.5" y="-566.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_TYPE_CLUSTER</text>
+<polygon fill="#f2e9ce" stroke="transparent" points="1318.5,-560 1318.5,-579 1386.5,-579 1386.5,-560 1318.5,-560"/>
+<text text-anchor="start" x="1337.5" y="-565.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
+<text text-anchor="start" x="1106.5" y="-546.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENDPOINT_TYPE_REF</text>
+<text text-anchor="start" x="1286.5" y="-546.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1320.5" y="-546.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1106.5" y="-527.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">CLUSTER_REF</text>
+<text text-anchor="start" x="1286.5" y="-527.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1320.5" y="-527.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1106.5" y="-508.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SIDE</text>
+<text text-anchor="start" x="1286.5" y="-508.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1320.5" y="-508.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
+<text text-anchor="start" x="1106.5" y="-489.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENABLED</text>
+<text text-anchor="start" x="1286.5" y="-489.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1320.5" y="-489.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<polygon fill="none" stroke="#888888" points="1103.5,-483.5 1103.5,-580.5 1387.5,-580.5 1387.5,-483.5 1103.5,-483.5"/>
 </g>
 <!-- endpoint_type_cluster_c12e3c9e&#45;&gt;cluster_5ec71239 -->
-<g id="edge5" class="edge">
+<g id="edge7" class="edge">
 <title>endpoint_type_cluster_c12e3c9e:w&#45;&gt;cluster_5ec71239:e</title>
-<path fill="none" stroke="#000000" d="M1031.0635,-665.2243C945.4934,-645.8144 1084.209,-472.4204 996,-400 939.3218,-353.4666 722.2441,-352.9428 666,-400 581.8779,-470.3817 724.5789,-639.6193 631.1374,-650.4541"/>
-<polygon fill="#000000" stroke="#000000" points="1039.0486,-666.0148 1048.5567,-671.4781 1044.0243,-666.5074 1049,-667 1049,-667 1049,-667 1044.0243,-666.5074 1049.4433,-662.5219 1039.0486,-666.0148 1039.0486,-666.0148"/>
-<ellipse fill="none" stroke="#000000" cx="1035.0681" cy="-665.6207" rx="4" ry="4"/>
+<path fill="none" stroke="#000000" d="M1086.5685,-528.8405C1060.4114,-521.6777 1053.8679,-497.5853 1032,-470 1010.0212,-442.2748 1026.1483,-417.5158 996,-399 933.5109,-360.6218 722.2278,-351.9234 666,-399 581.5776,-469.6825 724.9693,-639.5752 631.1761,-650.4519"/>
+<polygon fill="#000000" stroke="#000000" points="1094.5717,-529.8043 1103.9619,-535.4677 1099.5359,-530.4022 1104.5,-531 1104.5,-531 1104.5,-531 1099.5359,-530.4022 1105.0381,-526.5323 1094.5717,-529.8043 1094.5717,-529.8043"/>
+<ellipse fill="none" stroke="#000000" cx="1090.6004" cy="-529.326" rx="4" ry="4"/>
 <polygon fill="#000000" stroke="#000000" points="622.2675,-655.939 621.7296,-645.9534 623.7267,-645.8459 624.2646,-655.8314 622.2675,-655.939"/>
 <polyline fill="none" stroke="#000000" points="621,-651 625.9928,-650.7311 "/>
-<polygon fill="#000000" stroke="#000000" points="627.2602,-655.67 626.7224,-645.6845 628.7195,-645.5769 629.2574,-655.5625 627.2602,-655.67"/>
+<polygon fill="#000000" stroke="#000000" points="627.2603,-655.67 626.7224,-645.6845 628.7195,-645.5769 629.2574,-655.5625 627.2603,-655.67"/>
 <polyline fill="none" stroke="#000000" points="625.9928,-650.7311 630.9855,-650.4621 "/>
 </g>
-<!-- endpoint_type_9857dc03 -->
-<g id="node10" class="node">
-<title>endpoint_type_9857dc03</title>
-<polygon fill="#ffffff" stroke="transparent" points="678.5,-906 678.5,-1022 983.5,-1022 983.5,-906 678.5,-906"/>
-<polygon fill="#f2e9ce" stroke="transparent" points="680,-1002 680,-1021 850,-1021 850,-1002 680,-1002"/>
-<text text-anchor="start" x="682" y="-1008.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_TYPE</text>
-<polygon fill="#f2e9ce" stroke="transparent" points="850,-1002 850,-1021 983,-1021 983,-1002 850,-1002"/>
-<text text-anchor="start" x="934" y="-1007.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
-<text text-anchor="start" x="682" y="-989.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_TYPE_ID</text>
-<text text-anchor="start" x="843" y="-988.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="852" y="-988.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<text text-anchor="start" x="843" y="-969.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="852" y="-969.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">auto&#45;incremented</text>
-<text text-anchor="start" x="682" y="-950.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SESSION_REF</text>
-<text text-anchor="start" x="843" y="-950.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="852" y="-950.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<text text-anchor="start" x="682" y="-931.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">NAME</text>
-<text text-anchor="start" x="843" y="-931.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="852" y="-931.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
-<text text-anchor="start" x="682" y="-912.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">DEVICE_TYPE_REF</text>
-<text text-anchor="start" x="843" y="-912.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="852" y="-912.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<polygon fill="none" stroke="#888888" points="678.5,-906 678.5,-1022 983.5,-1022 983.5,-906 678.5,-906"/>
-</g>
 <!-- endpoint_type_cluster_c12e3c9e&#45;&gt;endpoint_type_9857dc03 -->
-<g id="edge10" class="edge">
+<g id="edge14" class="edge">
 <title>endpoint_type_cluster_c12e3c9e:w&#45;&gt;endpoint_type_9857dc03:e</title>
-<path fill="none" stroke="#000000" d="M1031.0515,-689.1174C932.5324,-715.414 1105.4002,-978.0467 993.1548,-992.3898"/>
-<polygon fill="#000000" stroke="#000000" points="1039.0689,-688.1717 1049.5272,-691.469 1044.0344,-687.5858 1049,-687 1049,-687 1049,-687 1044.0344,-687.5858 1048.4728,-682.531 1039.0689,-688.1717 1039.0689,-688.1717"/>
-<ellipse fill="none" stroke="#000000" cx="1035.0964" cy="-688.6403" rx="4" ry="4"/>
-<polygon fill="#000000" stroke="#000000" points="984.2982,-997.931 983.6982,-987.949 985.6946,-987.829 986.2946,-997.811 984.2982,-997.931"/>
-<polyline fill="none" stroke="#000000" points="983,-993 987.991,-992.7 "/>
-<polygon fill="#000000" stroke="#000000" points="989.2892,-997.631 988.6892,-987.6491 990.6856,-987.5291 991.2856,-997.5111 989.2892,-997.631"/>
-<polyline fill="none" stroke="#000000" points="987.991,-992.7 992.982,-992.4001 "/>
+<path fill="none" stroke="#000000" d="M1086.3546,-552.1724C1061.6073,-555.8125 1048.7811,-568.2545 1032,-594 995.4559,-650.0659 1004.3139,-826.5941 996,-893 990.9325,-933.4758 1021.4473,-983.1114 993.1801,-991.7036"/>
+<polygon fill="#000000" stroke="#000000" points="1094.5208,-551.6448 1104.7902,-555.4906 1099.5104,-551.3224 1104.5,-551 1104.5,-551 1104.5,-551 1099.5104,-551.3224 1104.2098,-546.5094 1094.5208,-551.6448 1094.5208,-551.6448"/>
+<ellipse fill="none" stroke="#000000" cx="1090.5291" cy="-551.9027" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="984.6237,-997.8336 983.3603,-987.9137 985.3443,-987.6611 986.6076,-997.5809 984.6237,-997.8336"/>
+<polyline fill="none" stroke="#000000" points="983,-993 987.9599,-992.3683 "/>
+<polygon fill="#000000" stroke="#000000" points="989.5836,-997.2019 988.3203,-987.2821 990.3042,-987.0294 991.5676,-996.9493 989.5836,-997.2019"/>
+<polyline fill="none" stroke="#000000" points="987.9599,-992.3683 992.9199,-991.7367 "/>
 </g>
 <!-- command_arg_294e7f81 -->
-<g id="node8" class="node">
+<g id="node10" class="node">
 <title>command_arg_294e7f81</title>
-<polygon fill="#ffffff" stroke="transparent" points="1088.5,-251.5 1088.5,-348.5 1291.5,-348.5 1291.5,-251.5 1088.5,-251.5"/>
-<polygon fill="#f2e9ce" stroke="transparent" points="1090,-328 1090,-347 1223,-347 1223,-328 1090,-328"/>
-<text text-anchor="start" x="1092" y="-334.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">COMMAND_ARG</text>
-<polygon fill="#f2e9ce" stroke="transparent" points="1223,-328 1223,-347 1291,-347 1291,-328 1223,-328"/>
-<text text-anchor="start" x="1242" y="-333.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
-<text text-anchor="start" x="1092" y="-314.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">COMMAND_REF</text>
-<text text-anchor="start" x="1212" y="-314.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1225" y="-314.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<text text-anchor="start" x="1092" y="-295.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">NAME</text>
-<text text-anchor="start" x="1212" y="-295.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1225" y="-295.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
-<text text-anchor="start" x="1092" y="-276.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TYPE</text>
-<text text-anchor="start" x="1212" y="-276.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1225" y="-276.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
-<text text-anchor="start" x="1092" y="-257.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">IS_ARRAY</text>
-<text text-anchor="start" x="1212" y="-257.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1225" y="-257.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<polygon fill="none" stroke="#888888" points="1088.5,-251.5 1088.5,-348.5 1291.5,-348.5 1291.5,-251.5 1088.5,-251.5"/>
+<polygon fill="#ffffff" stroke="transparent" points="1144,-237.5 1144,-334.5 1347,-334.5 1347,-237.5 1144,-237.5"/>
+<polygon fill="#f2e9ce" stroke="transparent" points="1145.5,-314 1145.5,-333 1278.5,-333 1278.5,-314 1145.5,-314"/>
+<text text-anchor="start" x="1147.5" y="-320.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">COMMAND_ARG</text>
+<polygon fill="#f2e9ce" stroke="transparent" points="1278.5,-314 1278.5,-333 1346.5,-333 1346.5,-314 1278.5,-314"/>
+<text text-anchor="start" x="1297.5" y="-319.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
+<text text-anchor="start" x="1147.5" y="-300.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">COMMAND_REF</text>
+<text text-anchor="start" x="1267.5" y="-300.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1280.5" y="-300.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1147.5" y="-281.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">NAME</text>
+<text text-anchor="start" x="1267.5" y="-281.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1280.5" y="-281.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
+<text text-anchor="start" x="1147.5" y="-262.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TYPE</text>
+<text text-anchor="start" x="1267.5" y="-262.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1280.5" y="-262.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
+<text text-anchor="start" x="1147.5" y="-243.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">IS_ARRAY</text>
+<text text-anchor="start" x="1267.5" y="-243.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1280.5" y="-243.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<polygon fill="none" stroke="#888888" points="1144,-237.5 1144,-334.5 1347,-334.5 1347,-237.5 1144,-237.5"/>
 </g>
 <!-- command_arg_294e7f81&#45;&gt;command_6371df8a -->
-<g id="edge6" class="edge">
+<g id="edge8" class="edge">
 <title>command_arg_294e7f81:w&#45;&gt;command_6371df8a:e</title>
-<path fill="none" stroke="#000000" d="M1071.6595,-319C1043.0298,-319 1028.7775,-319 997.3423,-319"/>
-<polygon fill="#000000" stroke="#000000" points="1080,-319.0001 1090,-323.5 1085,-319 1090,-319 1090,-319 1090,-319 1085,-319 1090,-314.5 1080,-319.0001 1080,-319.0001"/>
-<ellipse fill="none" stroke="#000000" cx="1076" cy="-319.0001" rx="4" ry="4"/>
-<polygon fill="#000000" stroke="#000000" points="988,-324 988,-314 990,-314 990,-324 988,-324"/>
-<polyline fill="none" stroke="#000000" points="987,-319 992,-319 "/>
-<polygon fill="#000000" stroke="#000000" points="993,-324.0001 993,-314.0001 995,-314.0001 995,-324.0001 993,-324.0001"/>
-<polyline fill="none" stroke="#000000" points="992,-319 997,-319.0001 "/>
+<path fill="none" stroke="#000000" d="M1127.2981,-305.3323C1074.2646,-307.3364 1053.5192,-317.7652 997.1533,-318.8998"/>
+<polygon fill="#000000" stroke="#000000" points="1135.5017,-305.1826 1145.5822,-309.4993 1140.5008,-305.0913 1145.5,-305 1145.5,-305 1145.5,-305 1140.5008,-305.0913 1145.4178,-300.5007 1135.5017,-305.1826 1135.5017,-305.1826"/>
+<ellipse fill="none" stroke="#000000" cx="1131.5023" cy="-305.2556" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="988.0493,-323.9899 987.9506,-313.9904 989.9505,-313.9706 990.0492,-323.9701 988.0493,-323.9899"/>
+<polyline fill="none" stroke="#000000" points="987,-319 991.9998,-318.9506 "/>
+<polygon fill="#000000" stroke="#000000" points="993.0491,-323.9405 992.9503,-313.941 994.9502,-313.9212 995.049,-323.9208 993.0491,-323.9405"/>
+<polyline fill="none" stroke="#000000" points="991.9998,-318.9506 996.9995,-318.9012 "/>
+</g>
+<!-- endpoint_type_command_c5d909ef -->
+<g id="node11" class="node">
+<title>endpoint_type_command_c5d909ef</title>
+<polygon fill="#ffffff" stroke="transparent" points="1095.5,-360.5 1095.5,-457.5 1395.5,-457.5 1395.5,-360.5 1095.5,-360.5"/>
+<polygon fill="#f2e9ce" stroke="transparent" points="1096.5,-437 1096.5,-456 1326.5,-456 1326.5,-437 1096.5,-437"/>
+<text text-anchor="start" x="1098.5" y="-443.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_TYPE_COMMAND</text>
+<polygon fill="#f2e9ce" stroke="transparent" points="1326.5,-437 1326.5,-456 1394.5,-456 1394.5,-437 1326.5,-437"/>
+<text text-anchor="start" x="1345.5" y="-442.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
+<text text-anchor="start" x="1098.5" y="-423.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENDPOINT_TYPE_REF</text>
+<text text-anchor="start" x="1286.5" y="-423.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-423.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-404.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">COMMAND_REF</text>
+<text text-anchor="start" x="1286.5" y="-404.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-404.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-385.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INCOMING</text>
+<text text-anchor="start" x="1286.5" y="-385.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-385.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-366.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">OUTGOING</text>
+<text text-anchor="start" x="1286.5" y="-366.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1328.5" y="-366.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<polygon fill="none" stroke="#888888" points="1095.5,-360.5 1095.5,-457.5 1395.5,-457.5 1395.5,-360.5 1095.5,-360.5"/>
+</g>
+<!-- endpoint_type_command_c5d909ef&#45;&gt;command_6371df8a -->
+<g id="edge9" class="edge">
+<title>endpoint_type_command_c5d909ef:w&#45;&gt;command_6371df8a:e</title>
+<path fill="none" stroke="#000000" d="M1079.5393,-401.3105C1053.4549,-383.119 1021.8916,-333.3218 996.9164,-321.5283"/>
+<polygon fill="#000000" stroke="#000000" points="1087.1974,-404.3309 1094.8489,-412.1862 1091.8487,-406.1655 1096.5,-408 1096.5,-408 1096.5,-408 1091.8487,-406.1655 1098.1511,-403.8138 1087.1974,-404.3309 1087.1974,-404.3309"/>
+<ellipse fill="none" stroke="#000000" cx="1083.4764" cy="-402.8633" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="986.7336,-324.0921 989.2044,-314.4021 991.1424,-314.8962 988.6716,-324.5862 986.7336,-324.0921"/>
+<polyline fill="none" stroke="#000000" points="987,-319 991.845,-320.2354 "/>
+<polygon fill="#000000" stroke="#000000" points="991.5786,-325.3274 994.0494,-315.6374 995.9874,-316.1316 993.5166,-325.8216 991.5786,-325.3274"/>
+<polyline fill="none" stroke="#000000" points="991.845,-320.2354 996.69,-321.4707 "/>
+</g>
+<!-- endpoint_type_command_c5d909ef&#45;&gt;endpoint_type_9857dc03 -->
+<g id="edge15" class="edge">
+<title>endpoint_type_command_c5d909ef:w&#45;&gt;endpoint_type_9857dc03:e</title>
+<path fill="none" stroke="#000000" d="M1078.4048,-429.5378C1057.029,-433.7017 1046.0664,-446.4938 1032,-470 983.557,-550.9523 1006.0834,-799.2006 996,-893 991.64,-933.5581 1021.5745,-983.1262 993.1972,-991.7056"/>
+<polygon fill="#000000" stroke="#000000" points="1086.5359,-428.8468 1096.8811,-432.4838 1091.518,-428.4234 1096.5,-428 1096.5,-428 1096.5,-428 1091.518,-428.4234 1096.1189,-423.5162 1086.5359,-428.8468 1086.5359,-428.8468"/>
+<ellipse fill="none" stroke="#000000" cx="1082.5503" cy="-429.1856" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="984.6217,-997.8343 983.3624,-987.9139 985.3465,-987.662 986.6058,-997.5824 984.6217,-997.8343"/>
+<polyline fill="none" stroke="#000000" points="983,-993 987.9602,-992.3703 "/>
+<polygon fill="#000000" stroke="#000000" points="989.5819,-997.2046 988.3226,-987.2842 990.3067,-987.0323 991.566,-996.9527 989.5819,-997.2046"/>
+<polyline fill="none" stroke="#000000" points="987.9602,-992.3703 992.9204,-991.7407 "/>
 </g>
 <!-- device_type_2620a7e2&#45;&gt;package_fab13485 -->
-<g id="edge14" class="edge">
+<g id="edge20" class="edge">
 <title>device_type_2620a7e2:w&#45;&gt;package_fab13485:e</title>
 <path fill="none" stroke="#000000" d="M308.4517,-807.8467C284.3678,-790.2506 296.3184,-733.0966 265.0357,-723.4032"/>
 <polygon fill="#000000" stroke="#000000" points="316.4052,-810.1823 324.732,-817.3177 321.2026,-811.5912 326,-813 326,-813 326,-813 321.2026,-811.5912 327.268,-808.6823 316.4052,-810.1823 316.4052,-810.1823"/>
@@ -448,7 +598,7 @@
 <polyline fill="none" stroke="#000000" points="259.9518,-722.6924 264.9037,-723.3848 "/>
 </g>
 <!-- endpoint_type_9857dc03&#45;&gt;device_type_2620a7e2 -->
-<g id="edge8" class="edge">
+<g id="edge11" class="edge">
 <title>endpoint_type_9857dc03:w&#45;&gt;device_type_2620a7e2:e</title>
 <path fill="none" stroke="#000000" d="M662.2477,-911.3254C640.6788,-897.9351 640.8404,-859.9114 614.1508,-852.326"/>
 <polygon fill="#000000" stroke="#000000" points="670.3297,-913.4535 678.8541,-920.3517 675.1648,-914.7268 680,-916 680,-916 680,-916 675.1648,-914.7268 681.1459,-911.6483 670.3297,-913.4535 670.3297,-913.4535"/>
@@ -459,9 +609,9 @@
 <polyline fill="none" stroke="#000000" points="608.9579,-851.6477 613.9158,-852.2954 "/>
 </g>
 <!-- session_a11c82d5 -->
-<g id="node17" class="node">
+<g id="node20" class="node">
 <title>session_a11c82d5</title>
-<polygon fill="#ffffff" stroke="transparent" points="333.5,-967 333.5,-1083 596.5,-1083 596.5,-967 333.5,-967"/>
+<polygon fill="#ffffff" stroke="transparent" points="333.5,-948.5 333.5,-1083.5 596.5,-1083.5 596.5,-948.5 333.5,-948.5"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="335,-1063 335,-1082 463,-1082 463,-1063 335,-1063"/>
 <text text-anchor="start" x="337" y="-1069.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">SESSION</text>
 <polygon fill="#f2e9ce" stroke="transparent" points="463,-1063 463,-1082 596,-1082 596,-1063 463,-1063"/>
@@ -480,10 +630,13 @@
 <text text-anchor="start" x="337" y="-973.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">CREATION_TIME</text>
 <text text-anchor="start" x="456" y="-973.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
 <text text-anchor="start" x="465" y="-973.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<polygon fill="none" stroke="#888888" points="333.5,-967 333.5,-1083 596.5,-1083 596.5,-967 333.5,-967"/>
+<text text-anchor="start" x="337" y="-954.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">DIRTY</text>
+<text text-anchor="start" x="456" y="-954.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="465" y="-954.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<polygon fill="none" stroke="#888888" points="333.5,-948.5 333.5,-1083.5 596.5,-1083.5 596.5,-948.5 333.5,-948.5"/>
 </g>
 <!-- endpoint_type_9857dc03&#45;&gt;session_a11c82d5 -->
-<g id="edge19" class="edge">
+<g id="edge25" class="edge">
 <title>endpoint_type_9857dc03:w&#45;&gt;session_a11c82d5:e</title>
 <path fill="none" stroke="#000000" d="M662.1064,-958.2969C631.0588,-976.0169 644.3691,-1042.9516 606.2174,-1052.7896"/>
 <polygon fill="#000000" stroke="#000000" points="670.2764,-956.335 681.0508,-958.3756 675.1382,-955.1675 680,-954 680,-954 680,-954 675.1382,-955.1675 678.9492,-949.6244 670.2764,-956.335 670.2764,-956.335"/>
@@ -494,7 +647,7 @@
 <polyline fill="none" stroke="#000000" points="600.9653,-1053.4117 605.9306,-1052.8235 "/>
 </g>
 <!-- domain_78873d23 -->
-<g id="node11" class="node">
+<g id="node14" class="node">
 <title>domain_78873d23</title>
 <polygon fill="#ffffff" stroke="transparent" points="341,-384.5 341,-481.5 589,-481.5 589,-384.5 341,-384.5"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="342,-461 342,-480 455,-480 455,-461 342,-461"/>
@@ -515,67 +668,70 @@
 <polygon fill="none" stroke="#888888" points="341,-384.5 341,-481.5 589,-481.5 589,-384.5 341,-384.5"/>
 </g>
 <!-- domain_78873d23&#45;&gt;package_fab13485 -->
-<g id="edge15" class="edge">
+<g id="edge21" class="edge">
 <title>domain_78873d23:w&#45;&gt;package_fab13485:e</title>
-<path fill="none" stroke="#000000" d="M324.3508,-417.084C304.7321,-428.7511 310.9756,-463.4239 300,-495 284.3028,-540.1598 303.3468,-697.551 264.7792,-719.4608"/>
-<polygon fill="#000000" stroke="#000000" points="332.2574,-415.2544 343.0145,-417.3842 337.1287,-414.1272 342,-413 342,-413 342,-413 337.1287,-414.1272 340.9855,-408.6158 332.2574,-415.2544 332.2574,-415.2544"/>
-<ellipse fill="none" stroke="#000000" cx="328.3604" cy="-416.1562" rx="4" ry="4"/>
-<polygon fill="#000000" stroke="#000000" points="257.2245,-726.5882 254.7113,-716.9091 256.6471,-716.4065 259.1603,-726.0856 257.2245,-726.5882"/>
-<polyline fill="none" stroke="#000000" points="255,-722 259.8395,-720.7434 "/>
-<polygon fill="#000000" stroke="#000000" points="262.064,-725.3316 259.5508,-715.6525 261.4866,-715.1499 263.9999,-724.8289 262.064,-725.3316"/>
-<polyline fill="none" stroke="#000000" points="259.8395,-720.7434 264.6791,-719.4868 "/>
+<path fill="none" stroke="#000000" d="M324.2134,-417.1951C305.037,-428.8651 310.8824,-462.9007 300,-494 284.142,-539.3184 303.5126,-697.4376 264.8165,-719.4491"/>
+<polygon fill="#000000" stroke="#000000" points="332.267,-415.2956 343.033,-417.3798 337.1335,-414.1478 342,-413 342,-413 342,-413 337.1335,-414.1478 340.967,-408.6202 332.267,-415.2956 332.267,-415.2956"/>
+<ellipse fill="none" stroke="#000000" cx="328.3739" cy="-416.2139" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="257.2254,-726.5878 254.7103,-716.9092 256.646,-716.4062 259.1611,-726.0847 257.2254,-726.5878"/>
+<polyline fill="none" stroke="#000000" points="255,-722 259.8393,-720.7424 "/>
+<polygon fill="#000000" stroke="#000000" points="262.0647,-725.3302 259.5496,-715.6516 261.4853,-715.1486 264.0004,-724.8272 262.0647,-725.3302"/>
+<polyline fill="none" stroke="#000000" points="259.8393,-720.7424 264.6786,-719.4848 "/>
 </g>
 <!-- endpoint_966d81f4 -->
-<g id="node12" class="node">
+<g id="node15" class="node">
 <title>endpoint_966d81f4</title>
-<polygon fill="#ffffff" stroke="transparent" points="1040,-966.5 1040,-1101.5 1340,-1101.5 1340,-966.5 1040,-966.5"/>
-<polygon fill="#f2e9ce" stroke="transparent" points="1041,-1081 1041,-1100 1206,-1100 1206,-1081 1041,-1081"/>
-<text text-anchor="start" x="1043" y="-1087.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT</text>
-<polygon fill="#f2e9ce" stroke="transparent" points="1206,-1081 1206,-1100 1339,-1100 1339,-1081 1206,-1081"/>
-<text text-anchor="start" x="1290" y="-1086.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
-<text text-anchor="start" x="1043" y="-1068.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_ID</text>
-<text text-anchor="start" x="1199" y="-1067.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1208" y="-1067.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<text text-anchor="start" x="1199" y="-1048.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1208" y="-1048.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">auto&#45;incremented</text>
-<text text-anchor="start" x="1043" y="-1029.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SESSION_REF</text>
-<text text-anchor="start" x="1199" y="-1029.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1208" y="-1029.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<text text-anchor="start" x="1043" y="-1010.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENDPOINT_TYPE_REF</text>
-<text text-anchor="start" x="1199" y="-1010.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1208" y="-1010.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<text text-anchor="start" x="1043" y="-991.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">PROFILE</text>
-<text text-anchor="start" x="1199" y="-991.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1208" y="-991.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<text text-anchor="start" x="1043" y="-972.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">NETWORK</text>
-<text text-anchor="start" x="1199" y="-972.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1208" y="-972.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
-<polygon fill="none" stroke="#888888" points="1040,-966.5 1040,-1101.5 1340,-1101.5 1340,-966.5 1040,-966.5"/>
+<polygon fill="#ffffff" stroke="transparent" points="1095.5,-967 1095.5,-1121 1395.5,-1121 1395.5,-967 1095.5,-967"/>
+<polygon fill="#f2e9ce" stroke="transparent" points="1096.5,-1101 1096.5,-1120 1261.5,-1120 1261.5,-1101 1096.5,-1101"/>
+<text text-anchor="start" x="1098.5" y="-1107.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT</text>
+<polygon fill="#f2e9ce" stroke="transparent" points="1261.5,-1101 1261.5,-1120 1394.5,-1120 1394.5,-1101 1261.5,-1101"/>
+<text text-anchor="start" x="1345.5" y="-1106.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
+<text text-anchor="start" x="1098.5" y="-1088.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">ENDPOINT_REF</text>
+<text text-anchor="start" x="1254.5" y="-1087.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1263.5" y="-1087.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1254.5" y="-1068.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1263.5" y="-1068.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">auto&#45;incremented</text>
+<text text-anchor="start" x="1098.5" y="-1049.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">SESSION_REF</text>
+<text text-anchor="start" x="1254.5" y="-1049.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1263.5" y="-1049.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-1030.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENDPOINT_ID</text>
+<text text-anchor="start" x="1254.5" y="-1030.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1263.5" y="-1030.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-1011.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">ENDPOINT_TYPE_REF</text>
+<text text-anchor="start" x="1254.5" y="-1011.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1263.5" y="-1011.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-992.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">PROFILE</text>
+<text text-anchor="start" x="1254.5" y="-992.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1263.5" y="-992.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<text text-anchor="start" x="1098.5" y="-973.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">NETWORK_ID</text>
+<text text-anchor="start" x="1254.5" y="-973.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1263.5" y="-973.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">INTEGER</text>
+<polygon fill="none" stroke="#888888" points="1095.5,-967 1095.5,-1121 1395.5,-1121 1395.5,-967 1095.5,-967"/>
 </g>
 <!-- endpoint_966d81f4&#45;&gt;endpoint_type_9857dc03 -->
-<g id="edge9" class="edge">
+<g id="edge12" class="edge">
 <title>endpoint_966d81f4:w&#45;&gt;endpoint_type_9857dc03:e</title>
-<path fill="none" stroke="#000000" d="M1022.9579,-1010.1483C1012.461,-1005.2225 1005.7928,-996.9806 992.9771,-994.063"/>
-<polygon fill="#000000" stroke="#000000" points="1031.2204,-1011.9121 1040.0605,-1018.4008 1036.1102,-1012.9561 1041,-1014 1041,-1014 1041,-1014 1036.1102,-1012.9561 1041.9395,-1009.5992 1031.2204,-1011.9121 1031.2204,-1011.9121"/>
-<ellipse fill="none" stroke="#000000" cx="1027.3085" cy="-1011.077" rx="4" ry="4"/>
-<polygon fill="#000000" stroke="#000000" points="983.4646,-998.0778 984.5241,-988.1341 986.5129,-988.346 985.4533,-998.2897 983.4646,-998.0778"/>
-<polyline fill="none" stroke="#000000" points="983,-993 987.9719,-993.5298 "/>
-<polygon fill="#000000" stroke="#000000" points="988.4365,-998.6076 989.496,-988.6639 991.4847,-988.8758 990.4252,-998.8195 988.4365,-998.6076"/>
-<polyline fill="none" stroke="#000000" points="987.9719,-993.5298 992.9437,-994.0595 "/>
+<path fill="none" stroke="#000000" d="M1078.4814,-1013.9975C1044.6934,-1010.0467 1030.1966,-995.6554 993.4221,-993.3209"/>
+<polygon fill="#000000" stroke="#000000" points="1086.5154,-1014.4445 1096.25,-1019.4931 1091.5077,-1014.7222 1096.5,-1015 1096.5,-1015 1096.5,-1015 1091.5077,-1014.7222 1096.75,-1010.5069 1086.5154,-1014.4445 1086.5154,-1014.4445"/>
+<ellipse fill="none" stroke="#000000" cx="1082.5216" cy="-1014.2222" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="983.8456,-998.0284 984.1535,-988.0332 986.1525,-988.0947 985.8446,-998.09 983.8456,-998.0284"/>
+<polyline fill="none" stroke="#000000" points="983,-993 987.9976,-993.1539 "/>
+<polygon fill="#000000" stroke="#000000" points="988.8432,-998.1824 989.1511,-988.1871 991.1502,-988.2487 990.8423,-998.2439 988.8432,-998.1824"/>
+<polyline fill="none" stroke="#000000" points="987.9976,-993.1539 992.9953,-993.3079 "/>
 </g>
 <!-- endpoint_966d81f4&#45;&gt;session_a11c82d5 -->
-<g id="edge18" class="edge">
+<g id="edge24" class="edge">
 <title>endpoint_966d81f4:w&#45;&gt;session_a11c82d5:e</title>
-<path fill="none" stroke="#000000" d="M1022.9043,-1033.7849C947.9523,-1037.2324 663.9276,-1050.9757 606.2062,-1053.5747"/>
-<polygon fill="#000000" stroke="#000000" points="1031.0094,-1033.4334 1041.195,-1037.4958 1036.0047,-1033.2167 1041,-1033 1041,-1033 1041,-1033 1036.0047,-1033.2167 1040.805,-1028.5042 1031.0094,-1033.4334 1031.0094,-1033.4334"/>
-<ellipse fill="none" stroke="#000000" cx="1027.0132" cy="-1033.6068" rx="4" ry="4"/>
-<polygon fill="#000000" stroke="#000000" points="597.2073,-1058.954 596.7909,-1048.9627 598.7892,-1048.8794 599.2056,-1058.8707 597.2073,-1058.954"/>
-<polyline fill="none" stroke="#000000" points="596,-1054 600.9957,-1053.7918 "/>
-<polygon fill="#000000" stroke="#000000" points="602.203,-1058.7458 601.7866,-1048.7545 603.7848,-1048.6712 604.2013,-1058.6625 602.203,-1058.7458"/>
-<polyline fill="none" stroke="#000000" points="600.9957,-1053.7918 605.9913,-1053.5836 "/>
+<path fill="none" stroke="#000000" d="M1078.3073,-1054C874.0726,-1054 814.1203,-1054 606.0226,-1054"/>
+<polygon fill="#000000" stroke="#000000" points="1086.5,-1054.0001 1096.5,-1058.5 1091.5,-1054 1096.5,-1054 1096.5,-1054 1096.5,-1054 1091.5,-1054 1096.5,-1049.5 1086.5,-1054.0001 1086.5,-1054.0001"/>
+<ellipse fill="none" stroke="#000000" cx="1082.5" cy="-1054.0001" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="597,-1059 597,-1049 599,-1049 599,-1059 597,-1059"/>
+<polyline fill="none" stroke="#000000" points="596,-1054 601,-1054 "/>
+<polygon fill="#000000" stroke="#000000" points="602,-1059.0001 602,-1049.0001 604,-1049.0001 604,-1059.0001 602,-1059.0001"/>
+<polyline fill="none" stroke="#000000" points="601,-1054 606,-1054.0001 "/>
 </g>
 <!-- enum_210160 -->
-<g id="node13" class="node">
+<g id="node16" class="node">
 <title>enum_210160</title>
 <polygon fill="#ffffff" stroke="transparent" points="341,-138 341,-254 589,-254 589,-138 341,-138"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="342,-234 342,-253 455,-253 455,-234 342,-234"/>
@@ -599,18 +755,18 @@
 <polygon fill="none" stroke="#888888" points="341,-138 341,-254 589,-254 589,-138 341,-138"/>
 </g>
 <!-- enum_210160&#45;&gt;package_fab13485 -->
-<g id="edge16" class="edge">
+<g id="edge22" class="edge">
 <title>enum_210160:w&#45;&gt;package_fab13485:e</title>
-<path fill="none" stroke="#000000" d="M323.8973,-188.003C266.1996,-202.6955 313.5431,-295.3919 300,-372 293.7076,-407.5939 294.0953,-675.0103 263.4757,-716.5768"/>
-<polygon fill="#000000" stroke="#000000" points="332.0607,-187.0998 342.4949,-190.4727 337.0303,-186.5499 342,-186 342,-186 342,-186 337.0303,-186.5499 341.5051,-181.5273 332.0607,-187.0998 332.0607,-187.0998"/>
-<ellipse fill="none" stroke="#000000" cx="328.0849" cy="-187.5397" rx="4" ry="4"/>
-<polygon fill="#000000" stroke="#000000" points="258.5372,-725.6727 253.1475,-717.2494 254.8321,-716.1714 260.2218,-724.5947 258.5372,-725.6727"/>
-<polyline fill="none" stroke="#000000" points="255,-722 259.2116,-719.3052 "/>
-<polygon fill="#000000" stroke="#000000" points="262.7488,-722.9778 257.3591,-714.5545 259.0438,-713.4766 264.4335,-721.8999 262.7488,-722.9778"/>
-<polyline fill="none" stroke="#000000" points="259.2116,-719.3052 263.4233,-716.6103 "/>
+<path fill="none" stroke="#000000" d="M323.9864,-187.9919C266.5585,-202.6033 313.5043,-294.7891 300,-371 293.6756,-406.6914 294.184,-674.8754 263.497,-716.5613"/>
+<polygon fill="#000000" stroke="#000000" points="332.0606,-187.0991 342.4946,-190.4727 337.0303,-186.5496 342,-186 342,-186 342,-186 337.0303,-186.5496 341.5054,-181.5273 332.0606,-187.0991 332.0606,-187.0991"/>
+<ellipse fill="none" stroke="#000000" cx="328.0848" cy="-187.5388" rx="4" ry="4"/>
+<polygon fill="#000000" stroke="#000000" points="258.5378,-725.6721 253.1467,-717.2497 254.8312,-716.1715 260.2222,-724.5939 258.5378,-725.6721"/>
+<polyline fill="none" stroke="#000000" points="255,-722 259.2112,-719.3045 "/>
+<polygon fill="#000000" stroke="#000000" points="262.749,-722.9766 257.358,-714.5542 259.0424,-713.476 264.4335,-721.8984 262.749,-722.9766"/>
+<polyline fill="none" stroke="#000000" points="259.2112,-719.3045 263.4224,-716.609 "/>
 </g>
 <!-- enum_item_b6420bf0 -->
-<g id="node14" class="node">
+<g id="node17" class="node">
 <title>enum_item_b6420bf0</title>
 <polygon fill="#ffffff" stroke="transparent" points="747,-52 747,-130 915,-130 915,-52 747,-52"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="748,-110 748,-129 846,-129 846,-110 748,-110"/>
@@ -629,7 +785,7 @@
 <polygon fill="none" stroke="#888888" points="747,-52 747,-130 915,-130 915,-52 747,-52"/>
 </g>
 <!-- enum_item_b6420bf0&#45;&gt;enum_210160 -->
-<g id="edge11" class="edge">
+<g id="edge17" class="edge">
 <title>enum_item_b6420bf0:w&#45;&gt;enum_210160:e</title>
 <path fill="none" stroke="#000000" d="M729.8624,-102.4304C703.5873,-107.0723 693.2884,-122.6029 666,-143 628.702,-170.8788 636.7217,-217.4181 598.2075,-224.1727"/>
 <polygon fill="#000000" stroke="#000000" points="738.031,-101.7863 748.3538,-105.4861 743.0155,-101.3931 748,-101 748,-101 748,-101 743.0155,-101.3931 747.6462,-96.5139 738.031,-101.7863 738.031,-101.7863"/>
@@ -640,7 +796,7 @@
 <polyline fill="none" stroke="#000000" points="592.9837,-224.596 597.9673,-224.1921 "/>
 </g>
 <!-- struct_9268f434 -->
-<g id="node16" class="node">
+<g id="node19" class="node">
 <title>struct_9268f434</title>
 <polygon fill="#ffffff" stroke="transparent" points="341,-1269.5 341,-1366.5 589,-1366.5 589,-1269.5 341,-1269.5"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="342,-1346 342,-1365 455,-1365 455,-1346 342,-1346"/>
@@ -661,7 +817,7 @@
 <polygon fill="none" stroke="#888888" points="341,-1269.5 341,-1366.5 589,-1366.5 589,-1269.5 341,-1269.5"/>
 </g>
 <!-- struct_9268f434&#45;&gt;package_fab13485 -->
-<g id="edge17" class="edge">
+<g id="edge23" class="edge">
 <title>struct_9268f434:w&#45;&gt;package_fab13485:e</title>
 <path fill="none" stroke="#000000" d="M324.2255,-1293.6943C311.6894,-1286.0646 308.1436,-1269.1584 300,-1250 278.2715,-1198.882 309.8902,-774.3279 264.1112,-726.3979"/>
 <polygon fill="#000000" stroke="#000000" points="332.2811,-1295.6456 340.9405,-1302.3735 337.1405,-1296.8228 342,-1298 342,-1298 342,-1298 337.1405,-1296.8228 343.0595,-1293.6265 332.2811,-1295.6456 332.2811,-1295.6456"/>
@@ -672,7 +828,7 @@
 <polyline fill="none" stroke="#000000" points="259.5029,-724.1735 264.0058,-726.347 "/>
 </g>
 <!-- session_key_value_334d9527 -->
-<g id="node18" class="node">
+<g id="node21" class="node">
 <title>session_key_value_334d9527</title>
 <polygon fill="#ffffff" stroke="transparent" points="710.5,-1086 710.5,-1164 951.5,-1164 951.5,-1086 710.5,-1086"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="712,-1144 712,-1163 883,-1163 883,-1144 712,-1144"/>
@@ -691,7 +847,7 @@
 <polygon fill="none" stroke="#888888" points="710.5,-1086 710.5,-1164 951.5,-1164 951.5,-1086 710.5,-1086"/>
 </g>
 <!-- session_key_value_334d9527&#45;&gt;session_a11c82d5 -->
-<g id="edge20" class="edge">
+<g id="edge26" class="edge">
 <title>session_key_value_334d9527:w&#45;&gt;session_a11c82d5:e</title>
 <path fill="none" stroke="#000000" d="M694.0704,-1132.3967C653.1944,-1119.426 652.0894,-1062.1081 606.1589,-1054.7734"/>
 <polygon fill="#000000" stroke="#000000" points="702.1038,-1133.5631 711.3534,-1139.4533 707.0519,-1134.2815 712,-1135 712,-1135 712,-1135 707.0519,-1134.2815 712.6466,-1130.5467 702.1038,-1133.5631 702.1038,-1133.5631"/>
@@ -702,26 +858,26 @@
 <polyline fill="none" stroke="#000000" points="600.9856,-1054.3796 605.9711,-1054.7592 "/>
 </g>
 <!-- setting_a12b0e8f -->
-<g id="node19" class="node">
+<g id="node22" class="node">
 <title>setting_a12b0e8f</title>
-<polygon fill="#ffffff" stroke="transparent" points="1119,-1128 1119,-1206 1261,-1206 1261,-1128 1119,-1128"/>
-<polygon fill="#f2e9ce" stroke="transparent" points="1120,-1186 1120,-1205 1209,-1205 1209,-1186 1120,-1186"/>
-<text text-anchor="start" x="1122" y="-1192.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">SETTING</text>
-<polygon fill="#f2e9ce" stroke="transparent" points="1209,-1186 1209,-1205 1260,-1205 1260,-1186 1209,-1186"/>
-<text text-anchor="start" x="1211" y="-1191.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
-<text text-anchor="start" x="1122" y="-1172.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">CATEGORY</text>
-<text text-anchor="start" x="1202" y="-1172.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1211" y="-1172.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
-<text text-anchor="start" x="1122" y="-1153.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">KEY</text>
-<text text-anchor="start" x="1202" y="-1153.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1211" y="-1153.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
-<text text-anchor="start" x="1122" y="-1134.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">&quot;VALUE&quot;</text>
-<text text-anchor="start" x="1202" y="-1134.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
-<text text-anchor="start" x="1211" y="-1134.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
-<polygon fill="none" stroke="#888888" points="1119,-1128 1119,-1206 1261,-1206 1261,-1128 1119,-1128"/>
+<polygon fill="#ffffff" stroke="transparent" points="1174.5,-1147 1174.5,-1225 1316.5,-1225 1316.5,-1147 1174.5,-1147"/>
+<polygon fill="#f2e9ce" stroke="transparent" points="1175.5,-1205 1175.5,-1224 1264.5,-1224 1264.5,-1205 1175.5,-1205"/>
+<text text-anchor="start" x="1177.5" y="-1211.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00" fill="#000000">SETTING</text>
+<polygon fill="#f2e9ce" stroke="transparent" points="1264.5,-1205 1264.5,-1224 1315.5,-1224 1315.5,-1205 1264.5,-1205"/>
+<text text-anchor="start" x="1266.5" y="-1210.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">[table]</text>
+<text text-anchor="start" x="1177.5" y="-1191.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">CATEGORY</text>
+<text text-anchor="start" x="1257.5" y="-1191.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1266.5" y="-1191.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
+<text text-anchor="start" x="1177.5" y="-1172.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">KEY</text>
+<text text-anchor="start" x="1257.5" y="-1172.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1266.5" y="-1172.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
+<text text-anchor="start" x="1177.5" y="-1153.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">&quot;VALUE&quot;</text>
+<text text-anchor="start" x="1257.5" y="-1153.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000"> </text>
+<text text-anchor="start" x="1266.5" y="-1153.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#000000">TEXT</text>
+<polygon fill="none" stroke="#888888" points="1174.5,-1147 1174.5,-1225 1316.5,-1225 1316.5,-1147 1174.5,-1147"/>
 </g>
 <!-- struct_item_d6e4bd9c -->
-<g id="node20" class="node">
+<g id="node23" class="node">
 <title>struct_item_d6e4bd9c</title>
 <polygon fill="#ffffff" stroke="transparent" points="739,-1294 739,-1372 923,-1372 923,-1294 739,-1294"/>
 <polygon fill="#f2e9ce" stroke="transparent" points="740,-1352 740,-1371 854,-1371 854,-1352 740,-1352"/>
@@ -740,7 +896,7 @@
 <polygon fill="none" stroke="#888888" points="739,-1294 739,-1372 923,-1372 923,-1294 739,-1294"/>
 </g>
 <!-- struct_item_d6e4bd9c&#45;&gt;struct_9268f434 -->
-<g id="edge21" class="edge">
+<g id="edge27" class="edge">
 <title>struct_item_d6e4bd9c:w&#45;&gt;struct_9268f434:e</title>
 <path fill="none" stroke="#000000" d="M721.8965,-1342.8457C671.7261,-1341.9597 651.4633,-1337.5431 598.0023,-1337.0456"/>
 <polygon fill="#000000" stroke="#000000" points="730.0004,-1342.9147 739.9616,-1347.4998 735.0002,-1342.9573 740,-1343 740,-1343 740,-1343 735.0002,-1342.9573 740.0384,-1338.5002 730.0004,-1342.9147 730.0004,-1342.9147"/>
diff --git a/package-lock.json b/package-lock.json
index 7d5eedaf..567dc0da 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,12 +25,12 @@
       }
     },
     "@babel/compat-data": {
-      "version": "7.8.5",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.5.tgz",
-      "integrity": "sha512-jWYUqQX/ObOhG1UiEkbH5SANsE/8oKXiQWjj7p7xgj9Zmnt//aUvyz4dBkK0HNsS8/cbyC5NmmH87VekW+mXFg==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.9.6.tgz",
+      "integrity": "sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g==",
       "dev": true,
       "requires": {
-        "browserslist": "^4.8.5",
+        "browserslist": "^4.11.1",
         "invariant": "^2.2.4",
         "semver": "^5.5.0"
       },
@@ -110,12 +110,12 @@
       },
       "dependencies": {
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -133,171 +133,26 @@
       },
       "dependencies": {
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
         }
       }
     },
-    "@babel/helper-call-delegate": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz",
-      "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-hoist-variables": "^7.8.3",
-        "@babel/traverse": "^7.8.3",
-        "@babel/types": "^7.8.3"
-      },
-      "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
-          "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.8.3"
-          }
-        },
-        "@babel/generator": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
-          "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.8.3",
-            "jsesc": "^2.5.1",
-            "lodash": "^4.17.13",
-            "source-map": "^0.5.0"
-          }
-        },
-        "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-get-function-arity": "^7.8.3",
-            "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
-          }
-        },
-        "@babel/helper-get-function-arity": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz",
-          "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.8.3"
-          }
-        },
-        "@babel/helper-split-export-declaration": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
-          "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.8.3"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
-          "dev": true,
-          "requires": {
-            "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
-            "js-tokens": "^4.0.0"
-          }
-        },
-        "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
-          "dev": true
-        },
-        "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
-          }
-        },
-        "@babel/traverse": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
-          "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.8.4",
-            "@babel/helper-function-name": "^7.8.3",
-            "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.8.4",
-            "@babel/types": "^7.8.3",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.13"
-          }
-        },
-        "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
-          "dev": true,
-          "requires": {
-            "esutils": "^2.0.2",
-            "lodash": "^4.17.13",
-            "to-fast-properties": "^2.0.0"
-          }
-        },
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
-          }
-        },
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        }
-      }
-    },
     "@babel/helper-compilation-targets": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz",
-      "integrity": "sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz",
+      "integrity": "sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw==",
       "dev": true,
       "requires": {
-        "@babel/compat-data": "^7.8.4",
-        "browserslist": "^4.8.5",
+        "@babel/compat-data": "^7.9.6",
+        "browserslist": "^4.11.1",
         "invariant": "^2.2.4",
         "levenary": "^1.1.1",
         "semver": "^5.5.0"
@@ -312,16 +167,16 @@
       }
     },
     "@babel/helper-create-class-features-plugin": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz",
-      "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.9.6.tgz",
+      "integrity": "sha512-6N9IeuyHvMBRyjNYOMJHrhwtu4WJMrYf8hVbEHD3pbbbmNOk1kmXSQs7bA4dYDUaIx4ZEzdnvo6NwC3WHd/Qow==",
       "dev": true,
       "requires": {
-        "@babel/helper-function-name": "^7.8.3",
+        "@babel/helper-function-name": "^7.9.5",
         "@babel/helper-member-expression-to-functions": "^7.8.3",
         "@babel/helper-optimise-call-expression": "^7.8.3",
         "@babel/helper-plugin-utils": "^7.8.3",
-        "@babel/helper-replace-supers": "^7.8.3",
+        "@babel/helper-replace-supers": "^7.9.6",
         "@babel/helper-split-export-declaration": "^7.8.3"
       },
       "dependencies": {
@@ -335,14 +190,14 @@
           }
         },
         "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
           "dev": true,
           "requires": {
             "@babel/helper-get-function-arity": "^7.8.3",
             "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/types": "^7.9.5"
           }
         },
         "@babel/helper-get-function-arity": {
@@ -370,40 +225,40 @@
           }
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -422,13 +277,14 @@
       }
     },
     "@babel/helper-create-regexp-features-plugin": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz",
-      "integrity": "sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==",
+      "version": "7.8.8",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz",
+      "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==",
       "dev": true,
       "requires": {
+        "@babel/helper-annotate-as-pure": "^7.8.3",
         "@babel/helper-regex": "^7.8.3",
-        "regexpu-core": "^4.6.0"
+        "regexpu-core": "^4.7.0"
       }
     },
     "@babel/helper-define-map": {
@@ -452,14 +308,14 @@
           }
         },
         "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
           "dev": true,
           "requires": {
             "@babel/helper-get-function-arity": "^7.8.3",
             "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/types": "^7.9.5"
           }
         },
         "@babel/helper-get-function-arity": {
@@ -472,40 +328,40 @@
           }
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -543,26 +399,26 @@
           }
         },
         "@babel/generator": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
-          "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
+          "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
           "dev": true,
           "requires": {
-            "@babel/types": "^7.8.3",
+            "@babel/types": "^7.9.6",
             "jsesc": "^2.5.1",
             "lodash": "^4.17.13",
             "source-map": "^0.5.0"
           }
         },
         "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
           "dev": true,
           "requires": {
             "@babel/helper-get-function-arity": "^7.8.3",
             "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/types": "^7.9.5"
           }
         },
         "@babel/helper-get-function-arity": {
@@ -584,57 +440,57 @@
           }
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/traverse": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
-          "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
+          "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.8.4",
-            "@babel/helper-function-name": "^7.8.3",
+            "@babel/generator": "^7.9.6",
+            "@babel/helper-function-name": "^7.9.5",
             "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.8.4",
-            "@babel/types": "^7.8.3",
+            "@babel/parser": "^7.9.6",
+            "@babel/types": "^7.9.6",
             "debug": "^4.1.0",
             "globals": "^11.1.0",
             "lodash": "^4.17.13"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -697,12 +553,12 @@
       },
       "dependencies": {
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -719,12 +575,12 @@
       },
       "dependencies": {
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -741,12 +597,12 @@
       },
       "dependencies": {
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -754,16 +610,17 @@
       }
     },
     "@babel/helper-module-transforms": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz",
-      "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==",
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz",
+      "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==",
       "dev": true,
       "requires": {
         "@babel/helper-module-imports": "^7.8.3",
+        "@babel/helper-replace-supers": "^7.8.6",
         "@babel/helper-simple-access": "^7.8.3",
         "@babel/helper-split-export-declaration": "^7.8.3",
-        "@babel/template": "^7.8.3",
-        "@babel/types": "^7.8.3",
+        "@babel/template": "^7.8.6",
+        "@babel/types": "^7.9.0",
         "lodash": "^4.17.13"
       },
       "dependencies": {
@@ -786,40 +643,40 @@
           }
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -847,12 +704,12 @@
       },
       "dependencies": {
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -897,26 +754,26 @@
           }
         },
         "@babel/generator": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
-          "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
+          "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
           "dev": true,
           "requires": {
-            "@babel/types": "^7.8.3",
+            "@babel/types": "^7.9.6",
             "jsesc": "^2.5.1",
             "lodash": "^4.17.13",
             "source-map": "^0.5.0"
           }
         },
         "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
           "dev": true,
           "requires": {
             "@babel/helper-get-function-arity": "^7.8.3",
             "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/types": "^7.9.5"
           }
         },
         "@babel/helper-get-function-arity": {
@@ -938,57 +795,57 @@
           }
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/traverse": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
-          "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
+          "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.8.4",
-            "@babel/helper-function-name": "^7.8.3",
+            "@babel/generator": "^7.9.6",
+            "@babel/helper-function-name": "^7.9.5",
             "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.8.4",
-            "@babel/types": "^7.8.3",
+            "@babel/parser": "^7.9.6",
+            "@babel/types": "^7.9.6",
             "debug": "^4.1.0",
             "globals": "^11.1.0",
             "lodash": "^4.17.13"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -1022,15 +879,15 @@
       }
     },
     "@babel/helper-replace-supers": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz",
-      "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz",
+      "integrity": "sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA==",
       "dev": true,
       "requires": {
         "@babel/helper-member-expression-to-functions": "^7.8.3",
         "@babel/helper-optimise-call-expression": "^7.8.3",
-        "@babel/traverse": "^7.8.3",
-        "@babel/types": "^7.8.3"
+        "@babel/traverse": "^7.9.6",
+        "@babel/types": "^7.9.6"
       },
       "dependencies": {
         "@babel/code-frame": {
@@ -1043,26 +900,26 @@
           }
         },
         "@babel/generator": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
-          "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
+          "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
           "dev": true,
           "requires": {
-            "@babel/types": "^7.8.3",
+            "@babel/types": "^7.9.6",
             "jsesc": "^2.5.1",
             "lodash": "^4.17.13",
             "source-map": "^0.5.0"
           }
         },
         "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
           "dev": true,
           "requires": {
             "@babel/helper-get-function-arity": "^7.8.3",
             "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/types": "^7.9.5"
           }
         },
         "@babel/helper-get-function-arity": {
@@ -1084,57 +941,57 @@
           }
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/traverse": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
-          "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
+          "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.8.4",
-            "@babel/helper-function-name": "^7.8.3",
+            "@babel/generator": "^7.9.6",
+            "@babel/helper-function-name": "^7.9.5",
             "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.8.4",
-            "@babel/types": "^7.8.3",
+            "@babel/parser": "^7.9.6",
+            "@babel/types": "^7.9.6",
             "debug": "^4.1.0",
             "globals": "^11.1.0",
             "lodash": "^4.17.13"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -1187,40 +1044,40 @@
           }
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -1247,6 +1104,12 @@
         "@babel/types": "^7.7.4"
       }
     },
+    "@babel/helper-validator-identifier": {
+      "version": "7.9.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
+      "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==",
+      "dev": true
+    },
     "@babel/helper-wrap-function": {
       "version": "7.8.3",
       "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz",
@@ -1269,26 +1132,26 @@
           }
         },
         "@babel/generator": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
-          "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
+          "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
           "dev": true,
           "requires": {
-            "@babel/types": "^7.8.3",
+            "@babel/types": "^7.9.6",
             "jsesc": "^2.5.1",
             "lodash": "^4.17.13",
             "source-map": "^0.5.0"
           }
         },
         "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
           "dev": true,
           "requires": {
             "@babel/helper-get-function-arity": "^7.8.3",
             "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/types": "^7.9.5"
           }
         },
         "@babel/helper-get-function-arity": {
@@ -1310,57 +1173,57 @@
           }
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/traverse": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
-          "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
+          "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.8.4",
-            "@babel/helper-function-name": "^7.8.3",
+            "@babel/generator": "^7.9.6",
+            "@babel/helper-function-name": "^7.9.5",
             "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.8.4",
-            "@babel/types": "^7.8.3",
+            "@babel/parser": "^7.9.6",
+            "@babel/types": "^7.9.6",
             "debug": "^4.1.0",
             "globals": "^11.1.0",
             "lodash": "^4.17.13"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -1609,13 +1472,14 @@
       }
     },
     "@babel/plugin-proposal-object-rest-spread": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz",
-      "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz",
+      "integrity": "sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.8.3",
-        "@babel/plugin-syntax-object-rest-spread": "^7.8.0"
+        "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+        "@babel/plugin-transform-parameters": "^7.9.5"
       },
       "dependencies": {
         "@babel/helper-plugin-utils": {
@@ -1654,9 +1518,9 @@
       }
     },
     "@babel/plugin-proposal-optional-chaining": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz",
-      "integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==",
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz",
+      "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.8.3",
@@ -1690,12 +1554,12 @@
       }
     },
     "@babel/plugin-proposal-unicode-property-regex": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz",
-      "integrity": "sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ==",
+      "version": "7.8.8",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz",
+      "integrity": "sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A==",
       "dev": true,
       "requires": {
-        "@babel/helper-create-regexp-features-plugin": "^7.8.3",
+        "@babel/helper-create-regexp-features-plugin": "^7.8.8",
         "@babel/helper-plugin-utils": "^7.8.3"
       },
       "dependencies": {
@@ -2001,17 +1865,17 @@
       }
     },
     "@babel/plugin-transform-classes": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz",
-      "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==",
+      "version": "7.9.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz",
+      "integrity": "sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg==",
       "dev": true,
       "requires": {
         "@babel/helper-annotate-as-pure": "^7.8.3",
         "@babel/helper-define-map": "^7.8.3",
-        "@babel/helper-function-name": "^7.8.3",
+        "@babel/helper-function-name": "^7.9.5",
         "@babel/helper-optimise-call-expression": "^7.8.3",
         "@babel/helper-plugin-utils": "^7.8.3",
-        "@babel/helper-replace-supers": "^7.8.3",
+        "@babel/helper-replace-supers": "^7.8.6",
         "@babel/helper-split-export-declaration": "^7.8.3",
         "globals": "^11.1.0"
       },
@@ -2026,14 +1890,14 @@
           }
         },
         "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
           "dev": true,
           "requires": {
             "@babel/helper-get-function-arity": "^7.8.3",
             "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/types": "^7.9.5"
           }
         },
         "@babel/helper-get-function-arity": {
@@ -2061,40 +1925,40 @@
           }
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -2130,9 +1994,9 @@
       }
     },
     "@babel/plugin-transform-destructuring": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz",
-      "integrity": "sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==",
+      "version": "7.9.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz",
+      "integrity": "sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.8.3"
@@ -2200,9 +2064,9 @@
       }
     },
     "@babel/plugin-transform-for-of": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz",
-      "integrity": "sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==",
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz",
+      "integrity": "sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.8.3"
@@ -2236,14 +2100,14 @@
           }
         },
         "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
           "dev": true,
           "requires": {
             "@babel/helper-get-function-arity": "^7.8.3",
             "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/types": "^7.9.5"
           }
         },
         "@babel/helper-get-function-arity": {
@@ -2262,40 +2126,40 @@
           "dev": true
         },
         "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+          "version": "7.9.0",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
           "dev": true,
           "requires": {
+            "@babel/helper-validator-identifier": "^7.9.0",
             "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
           "dev": true
         },
         "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+          "version": "7.8.6",
+          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+          "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
+            "@babel/parser": "^7.8.6",
+            "@babel/types": "^7.8.6"
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -2348,14 +2212,14 @@
       }
     },
     "@babel/plugin-transform-modules-amd": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz",
-      "integrity": "sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz",
+      "integrity": "sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-transforms": "^7.8.3",
+        "@babel/helper-module-transforms": "^7.9.0",
         "@babel/helper-plugin-utils": "^7.8.3",
-        "babel-plugin-dynamic-import-node": "^2.3.0"
+        "babel-plugin-dynamic-import-node": "^2.3.3"
       },
       "dependencies": {
         "@babel/helper-plugin-utils": {
@@ -2367,15 +2231,15 @@
       }
     },
     "@babel/plugin-transform-modules-commonjs": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz",
-      "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz",
+      "integrity": "sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-transforms": "^7.8.3",
+        "@babel/helper-module-transforms": "^7.9.0",
         "@babel/helper-plugin-utils": "^7.8.3",
         "@babel/helper-simple-access": "^7.8.3",
-        "babel-plugin-dynamic-import-node": "^2.3.0"
+        "babel-plugin-dynamic-import-node": "^2.3.3"
       },
       "dependencies": {
         "@babel/helper-plugin-utils": {
@@ -2387,15 +2251,15 @@
       }
     },
     "@babel/plugin-transform-modules-systemjs": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz",
-      "integrity": "sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz",
+      "integrity": "sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg==",
       "dev": true,
       "requires": {
         "@babel/helper-hoist-variables": "^7.8.3",
-        "@babel/helper-module-transforms": "^7.8.3",
+        "@babel/helper-module-transforms": "^7.9.0",
         "@babel/helper-plugin-utils": "^7.8.3",
-        "babel-plugin-dynamic-import-node": "^2.3.0"
+        "babel-plugin-dynamic-import-node": "^2.3.3"
       },
       "dependencies": {
         "@babel/helper-plugin-utils": {
@@ -2407,12 +2271,12 @@
       }
     },
     "@babel/plugin-transform-modules-umd": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz",
-      "integrity": "sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==",
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz",
+      "integrity": "sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-transforms": "^7.8.3",
+        "@babel/helper-module-transforms": "^7.9.0",
         "@babel/helper-plugin-utils": "^7.8.3"
       },
       "dependencies": {
@@ -2469,12 +2333,11 @@
       }
     },
     "@babel/plugin-transform-parameters": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz",
-      "integrity": "sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==",
+      "version": "7.9.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz",
+      "integrity": "sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA==",
       "dev": true,
       "requires": {
-        "@babel/helper-call-delegate": "^7.8.3",
         "@babel/helper-get-function-arity": "^7.8.3",
         "@babel/helper-plugin-utils": "^7.8.3"
       },
@@ -2495,12 +2358,12 @@
           "dev": true
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -2525,12 +2388,12 @@
       }
     },
     "@babel/plugin-transform-regenerator": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz",
-      "integrity": "sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==",
+      "version": "7.8.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz",
+      "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==",
       "dev": true,
       "requires": {
-        "regenerator-transform": "^0.14.0"
+        "regenerator-transform": "^0.14.2"
       }
     },
     "@babel/plugin-transform-reserved-words": {
@@ -2551,9 +2414,9 @@
       }
     },
     "@babel/plugin-transform-runtime": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz",
-      "integrity": "sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.6.tgz",
+      "integrity": "sha512-qcmiECD0mYOjOIt8YHNsAP1SxPooC/rDmfmiSK9BNY72EitdSc7l44WTEklaWuFtbOEBjNhWWyph/kOImbNJ4w==",
       "dev": true,
       "requires": {
         "@babel/helper-module-imports": "^7.8.3",
@@ -2682,27 +2545,29 @@
       }
     },
     "@babel/preset-env": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.4.tgz",
-      "integrity": "sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.6.tgz",
+      "integrity": "sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ==",
       "dev": true,
       "requires": {
-        "@babel/compat-data": "^7.8.4",
-        "@babel/helper-compilation-targets": "^7.8.4",
+        "@babel/compat-data": "^7.9.6",
+        "@babel/helper-compilation-targets": "^7.9.6",
         "@babel/helper-module-imports": "^7.8.3",
         "@babel/helper-plugin-utils": "^7.8.3",
         "@babel/plugin-proposal-async-generator-functions": "^7.8.3",
         "@babel/plugin-proposal-dynamic-import": "^7.8.3",
         "@babel/plugin-proposal-json-strings": "^7.8.3",
         "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
-        "@babel/plugin-proposal-object-rest-spread": "^7.8.3",
+        "@babel/plugin-proposal-numeric-separator": "^7.8.3",
+        "@babel/plugin-proposal-object-rest-spread": "^7.9.6",
         "@babel/plugin-proposal-optional-catch-binding": "^7.8.3",
-        "@babel/plugin-proposal-optional-chaining": "^7.8.3",
+        "@babel/plugin-proposal-optional-chaining": "^7.9.0",
         "@babel/plugin-proposal-unicode-property-regex": "^7.8.3",
         "@babel/plugin-syntax-async-generators": "^7.8.0",
         "@babel/plugin-syntax-dynamic-import": "^7.8.0",
         "@babel/plugin-syntax-json-strings": "^7.8.0",
         "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
+        "@babel/plugin-syntax-numeric-separator": "^7.8.0",
         "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
         "@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
         "@babel/plugin-syntax-optional-chaining": "^7.8.0",
@@ -2711,26 +2576,26 @@
         "@babel/plugin-transform-async-to-generator": "^7.8.3",
         "@babel/plugin-transform-block-scoped-functions": "^7.8.3",
         "@babel/plugin-transform-block-scoping": "^7.8.3",
-        "@babel/plugin-transform-classes": "^7.8.3",
+        "@babel/plugin-transform-classes": "^7.9.5",
         "@babel/plugin-transform-computed-properties": "^7.8.3",
-        "@babel/plugin-transform-destructuring": "^7.8.3",
+        "@babel/plugin-transform-destructuring": "^7.9.5",
         "@babel/plugin-transform-dotall-regex": "^7.8.3",
         "@babel/plugin-transform-duplicate-keys": "^7.8.3",
         "@babel/plugin-transform-exponentiation-operator": "^7.8.3",
-        "@babel/plugin-transform-for-of": "^7.8.4",
+        "@babel/plugin-transform-for-of": "^7.9.0",
         "@babel/plugin-transform-function-name": "^7.8.3",
         "@babel/plugin-transform-literals": "^7.8.3",
         "@babel/plugin-transform-member-expression-literals": "^7.8.3",
-        "@babel/plugin-transform-modules-amd": "^7.8.3",
-        "@babel/plugin-transform-modules-commonjs": "^7.8.3",
-        "@babel/plugin-transform-modules-systemjs": "^7.8.3",
-        "@babel/plugin-transform-modules-umd": "^7.8.3",
+        "@babel/plugin-transform-modules-amd": "^7.9.6",
+        "@babel/plugin-transform-modules-commonjs": "^7.9.6",
+        "@babel/plugin-transform-modules-systemjs": "^7.9.6",
+        "@babel/plugin-transform-modules-umd": "^7.9.0",
         "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3",
         "@babel/plugin-transform-new-target": "^7.8.3",
         "@babel/plugin-transform-object-super": "^7.8.3",
-        "@babel/plugin-transform-parameters": "^7.8.4",
+        "@babel/plugin-transform-parameters": "^7.9.5",
         "@babel/plugin-transform-property-literals": "^7.8.3",
-        "@babel/plugin-transform-regenerator": "^7.8.3",
+        "@babel/plugin-transform-regenerator": "^7.8.7",
         "@babel/plugin-transform-reserved-words": "^7.8.3",
         "@babel/plugin-transform-shorthand-properties": "^7.8.3",
         "@babel/plugin-transform-spread": "^7.8.3",
@@ -2738,8 +2603,9 @@
         "@babel/plugin-transform-template-literals": "^7.8.3",
         "@babel/plugin-transform-typeof-symbol": "^7.8.4",
         "@babel/plugin-transform-unicode-regex": "^7.8.3",
-        "@babel/types": "^7.8.3",
-        "browserslist": "^4.8.5",
+        "@babel/preset-modules": "^0.1.3",
+        "@babel/types": "^7.9.6",
+        "browserslist": "^4.11.1",
         "core-js-compat": "^3.6.2",
         "invariant": "^2.2.2",
         "levenary": "^1.1.1",
@@ -2771,12 +2637,12 @@
           }
         },
         "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+          "version": "7.9.6",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
           "dev": true,
           "requires": {
-            "esutils": "^2.0.2",
+            "@babel/helper-validator-identifier": "^7.9.5",
             "lodash": "^4.17.13",
             "to-fast-properties": "^2.0.0"
           }
@@ -2789,33 +2655,70 @@
         }
       }
     },
+    "@babel/preset-modules": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz",
+      "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.0.0",
+        "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+        "@babel/plugin-transform-dotall-regex": "^7.4.4",
+        "@babel/types": "^7.4.4",
+        "esutils": "^2.0.2"
+      }
+    },
     "@babel/runtime": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz",
-      "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.6.tgz",
+      "integrity": "sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==",
       "dev": true,
       "requires": {
-        "regenerator-runtime": "^0.13.2"
+        "regenerator-runtime": "^0.13.4"
+      },
+      "dependencies": {
+        "regenerator-runtime": {
+          "version": "0.13.5",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+          "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
+          "dev": true
+        }
       }
     },
     "@babel/runtime-corejs2": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.8.4.tgz",
-      "integrity": "sha512-7jU2FgNqNHX6yTuU/Dr/vH5/O8eVL9U85MG5aDw1LzGfCvvhXC1shdXfVzCQDsoY967yrAKeLujRv7l8BU+dZA==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.9.6.tgz",
+      "integrity": "sha512-TcdM3xc7weMrwTawuG3BTjtVE3mQLXUPQ9CxTbSKOrhn3QAcqCJ2fz+IIv25wztzUnhNZat7hr655YJa61F3zg==",
       "dev": true,
       "requires": {
         "core-js": "^2.6.5",
-        "regenerator-runtime": "^0.13.2"
+        "regenerator-runtime": "^0.13.4"
+      },
+      "dependencies": {
+        "regenerator-runtime": {
+          "version": "0.13.5",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+          "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
+          "dev": true
+        }
       }
     },
     "@babel/runtime-corejs3": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.8.4.tgz",
-      "integrity": "sha512-+wpLqy5+fbQhvbllvlJEVRIpYj+COUWnnsm+I4jZlA8Lo7/MJmBhGTCHyk1/RWfOqBRJ2MbadddG6QltTKTlrg==",
+      "version": "7.9.6",
+      "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.9.6.tgz",
+      "integrity": "sha512-6toWAfaALQjt3KMZQc6fABqZwUDDuWzz+cAfPhqyEnzxvdWOAkjwPNxgF8xlmo7OWLsSjaKjsskpKHRLaMArOA==",
       "dev": true,
       "requires": {
         "core-js-pure": "^3.0.0",
-        "regenerator-runtime": "^0.13.2"
+        "regenerator-runtime": "^0.13.4"
+      },
+      "dependencies": {
+        "regenerator-runtime": {
+          "version": "0.13.5",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+          "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
+          "dev": true
+        }
       }
     },
     "@babel/template": {
@@ -3498,112 +3401,198 @@
       "dev": true
     },
     "@quasar/app": {
-      "version": "1.5.8",
-      "resolved": "https://registry.npmjs.org/@quasar/app/-/app-1.5.8.tgz",
-      "integrity": "sha512-fIbVmHW7AHzWk0cWIsUY1gecqlYN6KqZIyNKJ+xzt2iHc9x5AYE/lMqw9Ku4DxTl0LvFli9aHNh0pJnDdwz6Tg==",
+      "version": "1.8.4",
+      "resolved": "https://registry.npmjs.org/@quasar/app/-/app-1.8.4.tgz",
+      "integrity": "sha512-rdrgE94+bykmy5d5rtgaA8ad0BFL/RzCGm5IlPizcyJyO+UOIXoY1jmi4RQrjpE8gzAj/JByvtocc5Rp0uMmtw==",
       "dev": true,
       "requires": {
         "@quasar/babel-preset-app": "1.1.9",
         "@quasar/fastclick": "1.1.4",
         "@types/cordova": "0.0.34",
         "@types/electron-packager": "14.0.0",
-        "@types/express": "4.17.2",
-        "@types/fs-extra": "8.0.1",
+        "@types/express": "4.17.6",
         "@types/lru-cache": "5.1.0",
         "@types/terser-webpack-plugin": "2.2.0",
-        "@types/webpack": "4.41.6",
+        "@types/webpack": "4.41.12",
         "@types/webpack-bundle-analyzer": "2.13.3",
-        "@types/webpack-dev-server": "3.10.0",
-        "@types/yargs": "15.0.3",
+        "@types/webpack-dev-server": "3.10.1",
         "@vue/preload-webpack-plugin": "1.1.1",
-        "autoprefixer": "9.7.4",
-        "chalk": "3.0.0",
+        "archiver": "4.0.1",
+        "autoprefixer": "9.7.6",
+        "chalk": "4.0.0",
         "chokidar": "3.3.1",
         "ci-info": "2.0.0",
         "compression-webpack-plugin": "3.1.0",
         "copy-webpack-plugin": "5.1.1",
-        "cross-spawn": "7.0.1",
-        "css-loader": "3.4.2",
+        "cross-spawn": "7.0.2",
+        "css-loader": "3.5.3",
         "cssnano": "4.1.10",
         "dot-prop": "5.2.0",
         "elementtree": "0.1.7",
         "express": "4.17.1",
-        "fast-glob": "3.1.1",
-        "file-loader": "^5.0.2",
+        "fast-glob": "3.2.2",
+        "file-loader": "^6.0.0",
+        "fork-ts-checker-webpack-plugin": "4.1.3",
         "friendly-errors-webpack-plugin": "1.7.0",
-        "fs-extra": "8.1.0",
+        "fs-extra": "9.0.0",
         "html-minifier": "4.0.0",
         "html-webpack-plugin": "3.2.0",
-        "inquirer": "7.0.1",
-        "isbinaryfile": "4.0.3",
+        "inquirer": "7.1.0",
+        "isbinaryfile": "4.0.6",
         "launch-editor-middleware": "2.2.1",
         "lodash.debounce": "4.0.8",
         "lodash.template": "4.5.0",
         "lodash.throttle": "4.1.1",
-        "log-update": "3.3.0",
+        "log-update": "4.0.0",
         "lru-cache": "5.1.1",
         "memory-fs": "0.5.0",
         "mini-css-extract-plugin": "^0.9.0",
-        "minimist": "1.2.0",
+        "minimist": "1.2.5",
         "ms": "2.1.2",
         "node-loader": "0.6.0",
-        "node-sass": "4.13.1",
-        "open": "7.0.2",
+        "node-sass": "4.14.0",
+        "open": "7.0.3",
         "optimize-css-assets-webpack-plugin": "5.0.3",
         "ouch": "2.0.0",
         "postcss-loader": "3.0.0",
-        "postcss-rtl": "1.5.0",
+        "postcss-rtl": "1.7.3",
         "postcss-safe-parser": "4.0.2",
-        "register-service-worker": "1.6.2",
+        "register-service-worker": "1.7.1",
         "sass-loader": "8.0.2",
-        "semver": "7.1.3",
+        "semver": "7.3.2",
         "strip-ansi": "6.0.0",
         "stylus": "0.54.7",
         "stylus-loader": "3.0.2",
-        "terser-webpack-plugin": "2.3.4",
-        "url-loader": "3.0.0",
+        "terser-webpack-plugin": "2.3.6",
+        "ts-loader": "7.0.1",
+        "typescript": "3.8.3",
+        "url-loader": "4.1.0",
         "vue": "2.6.11",
-        "vue-loader": "15.9.0",
-        "vue-router": "3.1.5",
+        "vue-loader": "15.9.1",
+        "vue-router": "3.1.6",
         "vue-server-renderer": "2.6.11",
         "vue-style-loader": "4.1.2",
         "vue-template-compiler": "2.6.11",
-        "vuex": "3.1.2",
-        "webpack": "4.41.6",
-        "webpack-bundle-analyzer": "3.6.0",
+        "vuex": "3.3.0",
+        "webpack": "4.43.0",
+        "webpack-bundle-analyzer": "3.7.0",
         "webpack-chain": "6.4.0",
         "webpack-dev-server": "3.10.3",
         "webpack-merge": "4.2.2",
         "webpack-node-externals": "1.7.2",
         "workbox-webpack-plugin": "4.3.1",
-        "yargs": "15.1.0"
+        "write-file-webpack-plugin": "4.5.1",
+        "yargs": "15.3.1"
       },
       "dependencies": {
-        "@types/yargs": {
-          "version": "15.0.3",
-          "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.3.tgz",
-          "integrity": "sha512-XCMQRK6kfpNBixHLyHUsGmXrpEmFFxzMrcnSXFMziHd8CoNJo8l16FkHyQq4x+xbM7E2XL83/O78OD8u+iZTdQ==",
+        "ajv": {
+          "version": "6.12.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+          "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
           "dev": true,
           "requires": {
-            "@types/yargs-parser": "*"
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
           }
         },
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+        "emojis-list": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+          "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
           "dev": true
         },
+        "fast-deep-equal": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+          "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+          "dev": true
+        },
+        "file-loader": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.0.0.tgz",
+          "integrity": "sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ==",
+          "dev": true,
+          "requires": {
+            "loader-utils": "^2.0.0",
+            "schema-utils": "^2.6.5"
+          }
+        },
+        "fs-extra": {
+          "version": "9.0.0",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz",
+          "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==",
+          "dev": true,
+          "requires": {
+            "at-least-node": "^1.0.0",
+            "graceful-fs": "^4.2.0",
+            "jsonfile": "^6.0.1",
+            "universalify": "^1.0.0"
+          }
+        },
+        "isbinaryfile": {
+          "version": "4.0.6",
+          "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz",
+          "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==",
+          "dev": true
+        },
+        "json5": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+          "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.5"
+          }
+        },
+        "jsonfile": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
+          "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.6",
+            "universalify": "^1.0.0"
+          }
+        },
+        "loader-utils": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+          "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+          "dev": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
         "ms": {
           "version": "2.1.2",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
           "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
         },
+        "schema-utils": {
+          "version": "2.6.6",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+          "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.12.0",
+            "ajv-keywords": "^3.4.1"
+          }
+        },
         "semver": {
-          "version": "7.1.3",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz",
-          "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==",
+          "version": "7.3.2",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+          "dev": true
+        },
+        "universalify": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
+          "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
           "dev": true
         }
       }
@@ -3636,9 +3625,9 @@
       }
     },
     "@quasar/extras": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.5.2.tgz",
-      "integrity": "sha512-4hwibnTNHM0OmZl6T3PN6CaHnVOmsCWpNwgFhJS0zMfsQ2z2s1OxObOFVDSSBuPT+sRk3iakhMLRaohNze0HYA=="
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.7.0.tgz",
+      "integrity": "sha512-3G/tQZiyrSNuwkFXVBdAH9WYYTMY0mwf9nCp23jTzqH7MjUbs6RTujFN+urKlyQ7fZRLXmdWvo34z3+DgrUmqQ=="
     },
     "@quasar/fastclick": {
       "version": "1.1.4",
@@ -3833,35 +3822,27 @@
       "dev": true
     },
     "@types/express": {
-      "version": "4.17.2",
-      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.2.tgz",
-      "integrity": "sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA==",
+      "version": "4.17.6",
+      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz",
+      "integrity": "sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w==",
       "dev": true,
       "requires": {
         "@types/body-parser": "*",
         "@types/express-serve-static-core": "*",
+        "@types/qs": "*",
         "@types/serve-static": "*"
       }
     },
     "@types/express-serve-static-core": {
-      "version": "4.17.2",
-      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz",
-      "integrity": "sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg==",
+      "version": "4.17.5",
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.5.tgz",
+      "integrity": "sha512-578YH5Lt88AKoADy0b2jQGwJtrBxezXtVe/MBqWXKZpqx91SnC0pVkVCcxcytz3lWW+cHBYDi3Ysh0WXc+rAYw==",
       "dev": true,
       "requires": {
         "@types/node": "*",
         "@types/range-parser": "*"
       }
     },
-    "@types/fs-extra": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.1.tgz",
-      "integrity": "sha512-J00cVDALmi/hJOYsunyT52Hva5TnJeKP5yd1r+mH/ZU0mbYZflR0Z5kw5kITtKTRYMhm1JMClOFYdHnQszEvqw==",
-      "dev": true,
-      "requires": {
-        "@types/node": "*"
-      }
-    },
     "@types/glob": {
       "version": "7.1.1",
       "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
@@ -3874,9 +3855,9 @@
       }
     },
     "@types/http-proxy": {
-      "version": "1.17.3",
-      "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.3.tgz",
-      "integrity": "sha512-wIPqXANye5BbORbuh74exbwNzj+UWCwWyeEFJzUQ7Fq3W2NSAy+7x7nX1fgbEypr2/TdKqpeuxLnXWgzN533/Q==",
+      "version": "1.17.4",
+      "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.4.tgz",
+      "integrity": "sha512-IrSHl2u6AWXduUaDLqYpt45tLVCtYv7o4Z0s1KghBCDgIIS9oW5K1H8mZG/A2CfeLdEa7rTd1ACOiHBc1EMT2Q==",
       "dev": true,
       "requires": {
         "@types/node": "*"
@@ -3946,9 +3927,9 @@
       "dev": true
     },
     "@types/node": {
-      "version": "12.12.17",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz",
-      "integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==",
+      "version": "13.13.4",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.4.tgz",
+      "integrity": "sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA==",
       "dev": true
     },
     "@types/q": {
@@ -3957,6 +3938,12 @@
       "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
       "dev": true
     },
+    "@types/qs": {
+      "version": "6.9.1",
+      "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.1.tgz",
+      "integrity": "sha512-lhbQXx9HKZAPgBkISrBcmAcMpZsmpe/Cd/hY7LGZS5OfkySUBItnPZHgQPssWYUET8elF+yCFBbP1Q0RZPTdaw==",
+      "dev": true
+    },
     "@types/range-parser": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
@@ -4014,9 +4001,9 @@
       }
     },
     "@types/uglify-js": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.0.4.tgz",
-      "integrity": "sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ==",
+      "version": "3.9.0",
+      "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.9.0.tgz",
+      "integrity": "sha512-3ZcoyPYHVOCcLpnfZwD47KFLr8W/mpUcgjpf1M4Q78TMJIw7KMAHSjiCLJp1z3ZrBR9pTLbe191O0TldFK5zcw==",
       "dev": true,
       "requires": {
         "source-map": "^0.6.1"
@@ -4031,9 +4018,9 @@
       }
     },
     "@types/webpack": {
-      "version": "4.41.6",
-      "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.6.tgz",
-      "integrity": "sha512-iWRpV5Ej+8uKrgxp6jXz3v7ZTjgtuMXY+rsxQjFNU0hYCnHkpA7vtiNffgxjuxX4feFHBbz0IF76OzX2OqDYPw==",
+      "version": "4.41.12",
+      "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.12.tgz",
+      "integrity": "sha512-BpCtM4NnBen6W+KEhrL9jKuZCXVtiH6+0b6cxdvNt2EwU949Al334PjQSl2BeAyvAX9mgoNNG21wvjP3xZJJ5w==",
       "dev": true,
       "requires": {
         "@types/anymatch": "*",
@@ -4062,9 +4049,9 @@
       }
     },
     "@types/webpack-dev-server": {
-      "version": "3.10.0",
-      "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-3.10.0.tgz",
-      "integrity": "sha512-ct/g/4WEEqOpXPqGX31TlZSzF1Sb7LXIViBz0oBSdH08XtNgY/hq/faXkw0yTxqvj7HJwS8dy2ggzqHposf1fQ==",
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-3.10.1.tgz",
+      "integrity": "sha512-2nwwQ/qHRghUirvG/gEDkOQDa+d881UTJM7EG9ok5KNaYCjYVvy7fdaO528Lcym9OQDn75SvruPYVVvMJxqO0g==",
       "dev": true,
       "requires": {
         "@types/connect-history-api-fallback": "*",
@@ -4075,9 +4062,9 @@
       }
     },
     "@types/webpack-sources": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.6.tgz",
-      "integrity": "sha512-FtAWR7wR5ocJ9+nP137DV81tveD/ZgB1sadnJ/axUGM3BUVfRPx8oQNMtv3JNfTeHx3VP7cXiyfR/jmtEsVHsQ==",
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.7.tgz",
+      "integrity": "sha512-XyaHrJILjK1VHVC4aVlKsdNN5KBTwufMb43cQs+flGxtPAf/1Qwl8+Q0tp5BwEGaI8D6XT1L+9bSWXckgkjTLw==",
       "dev": true,
       "requires": {
         "@types/node": "*",
@@ -4109,9 +4096,9 @@
       "dev": true
     },
     "@vue/component-compiler-utils": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.1.1.tgz",
-      "integrity": "sha512-+lN3nsfJJDGMNz7fCpcoYIORrXo0K3OTsdr8jCM7FuqdI4+70TY6gxY6viJ2Xi1clqyPg7LpeOWwjF31vSMmUw==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.1.2.tgz",
+      "integrity": "sha512-QLq9z8m79mCinpaEeSURhnNCN6djxpHw0lpP/bodMlt5kALfONpryMthvnrQOlTcIKoF+VoPi+lPHUYeDFPXug==",
       "dev": true,
       "requires": {
         "consolidate": "^0.15.1",
@@ -4180,178 +4167,177 @@
       }
     },
     "@webassemblyjs/ast": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
-      "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
+      "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/helper-module-context": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/wast-parser": "1.8.5"
+        "@webassemblyjs/helper-module-context": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/wast-parser": "1.9.0"
       }
     },
     "@webassemblyjs/floating-point-hex-parser": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz",
-      "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
+      "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==",
       "dev": true
     },
     "@webassemblyjs/helper-api-error": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz",
-      "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
+      "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==",
       "dev": true
     },
     "@webassemblyjs/helper-buffer": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz",
-      "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
+      "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==",
       "dev": true
     },
     "@webassemblyjs/helper-code-frame": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz",
-      "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
+      "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/wast-printer": "1.8.5"
+        "@webassemblyjs/wast-printer": "1.9.0"
       }
     },
     "@webassemblyjs/helper-fsm": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz",
-      "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
+      "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==",
       "dev": true
     },
     "@webassemblyjs/helper-module-context": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz",
-      "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
+      "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "mamacro": "^0.0.3"
+        "@webassemblyjs/ast": "1.9.0"
       }
     },
     "@webassemblyjs/helper-wasm-bytecode": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz",
-      "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
+      "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==",
       "dev": true
     },
     "@webassemblyjs/helper-wasm-section": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz",
-      "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz",
+      "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-buffer": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/wasm-gen": "1.8.5"
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0"
       }
     },
     "@webassemblyjs/ieee754": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz",
-      "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz",
+      "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==",
       "dev": true,
       "requires": {
         "@xtuc/ieee754": "^1.2.0"
       }
     },
     "@webassemblyjs/leb128": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz",
-      "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz",
+      "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==",
       "dev": true,
       "requires": {
         "@xtuc/long": "4.2.2"
       }
     },
     "@webassemblyjs/utf8": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz",
-      "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz",
+      "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==",
       "dev": true
     },
     "@webassemblyjs/wasm-edit": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz",
-      "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz",
+      "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-buffer": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/helper-wasm-section": "1.8.5",
-        "@webassemblyjs/wasm-gen": "1.8.5",
-        "@webassemblyjs/wasm-opt": "1.8.5",
-        "@webassemblyjs/wasm-parser": "1.8.5",
-        "@webassemblyjs/wast-printer": "1.8.5"
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/helper-wasm-section": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0",
+        "@webassemblyjs/wasm-opt": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0",
+        "@webassemblyjs/wast-printer": "1.9.0"
       }
     },
     "@webassemblyjs/wasm-gen": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz",
-      "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz",
+      "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/ieee754": "1.8.5",
-        "@webassemblyjs/leb128": "1.8.5",
-        "@webassemblyjs/utf8": "1.8.5"
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/ieee754": "1.9.0",
+        "@webassemblyjs/leb128": "1.9.0",
+        "@webassemblyjs/utf8": "1.9.0"
       }
     },
     "@webassemblyjs/wasm-opt": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz",
-      "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz",
+      "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-buffer": "1.8.5",
-        "@webassemblyjs/wasm-gen": "1.8.5",
-        "@webassemblyjs/wasm-parser": "1.8.5"
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-buffer": "1.9.0",
+        "@webassemblyjs/wasm-gen": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0"
       }
     },
     "@webassemblyjs/wasm-parser": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz",
-      "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz",
+      "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-api-error": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/ieee754": "1.8.5",
-        "@webassemblyjs/leb128": "1.8.5",
-        "@webassemblyjs/utf8": "1.8.5"
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-api-error": "1.9.0",
+        "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+        "@webassemblyjs/ieee754": "1.9.0",
+        "@webassemblyjs/leb128": "1.9.0",
+        "@webassemblyjs/utf8": "1.9.0"
       }
     },
     "@webassemblyjs/wast-parser": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz",
-      "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz",
+      "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/floating-point-hex-parser": "1.8.5",
-        "@webassemblyjs/helper-api-error": "1.8.5",
-        "@webassemblyjs/helper-code-frame": "1.8.5",
-        "@webassemblyjs/helper-fsm": "1.8.5",
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/floating-point-hex-parser": "1.9.0",
+        "@webassemblyjs/helper-api-error": "1.9.0",
+        "@webassemblyjs/helper-code-frame": "1.9.0",
+        "@webassemblyjs/helper-fsm": "1.9.0",
         "@xtuc/long": "4.2.2"
       }
     },
     "@webassemblyjs/wast-printer": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz",
-      "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz",
+      "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/wast-parser": "1.8.5",
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/wast-parser": "1.9.0",
         "@xtuc/long": "4.2.2"
       }
     },
@@ -4527,12 +4513,20 @@
       }
     },
     "ansi-escapes": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz",
-      "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==",
+      "version": "4.3.1",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz",
+      "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==",
       "dev": true,
       "requires": {
-        "type-fest": "^0.8.1"
+        "type-fest": "^0.11.0"
+      },
+      "dependencies": {
+        "type-fest": {
+          "version": "0.11.0",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz",
+          "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==",
+          "dev": true
+        }
       }
     },
     "ansi-html": {
@@ -4620,6 +4614,52 @@
       "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
       "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
     },
+    "archiver": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/archiver/-/archiver-4.0.1.tgz",
+      "integrity": "sha512-/YV1pU4Nhpf/rJArM23W6GTUjT0l++VbjykrCRua1TSXrn+yM8Qs7XvtwSiRse0iCe49EPNf7ktXnPsWuSb91Q==",
+      "dev": true,
+      "requires": {
+        "archiver-utils": "^2.1.0",
+        "async": "^2.6.3",
+        "buffer-crc32": "^0.2.1",
+        "glob": "^7.1.6",
+        "readable-stream": "^3.6.0",
+        "tar-stream": "^2.1.2",
+        "zip-stream": "^3.0.1"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
+    "archiver-utils": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz",
+      "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.4",
+        "graceful-fs": "^4.2.0",
+        "lazystream": "^1.0.0",
+        "lodash.defaults": "^4.2.0",
+        "lodash.difference": "^4.5.0",
+        "lodash.flatten": "^4.4.0",
+        "lodash.isplainobject": "^4.0.6",
+        "lodash.union": "^4.6.0",
+        "normalize-path": "^3.0.0",
+        "readable-stream": "^2.0.0"
+      }
+    },
     "are-we-there-yet": {
       "version": "1.1.5",
       "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
@@ -4846,12 +4886,23 @@
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
     },
+    "at-least-node": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+      "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+      "dev": true
+    },
     "atob": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
       "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
       "dev": true
     },
+    "atomic-sleep": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
+      "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="
+    },
     "author-regex": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz",
@@ -4859,18 +4910,18 @@
       "dev": true
     },
     "autoprefixer": {
-      "version": "9.7.4",
-      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.4.tgz",
-      "integrity": "sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g==",
+      "version": "9.7.6",
+      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.6.tgz",
+      "integrity": "sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ==",
       "dev": true,
       "requires": {
-        "browserslist": "^4.8.3",
-        "caniuse-lite": "^1.0.30001020",
+        "browserslist": "^4.11.1",
+        "caniuse-lite": "^1.0.30001039",
         "chalk": "^2.4.2",
         "normalize-range": "^0.1.2",
         "num2fraction": "^1.2.2",
-        "postcss": "^7.0.26",
-        "postcss-value-parser": "^4.0.2"
+        "postcss": "^7.0.27",
+        "postcss-value-parser": "^4.0.3"
       },
       "dependencies": {
         "chalk": {
@@ -4965,15 +5016,15 @@
       "dev": true
     },
     "babel-eslint": {
-      "version": "10.0.3",
-      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz",
-      "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==",
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
+      "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "@babel/parser": "^7.0.0",
-        "@babel/traverse": "^7.0.0",
-        "@babel/types": "^7.0.0",
+        "@babel/parser": "^7.7.0",
+        "@babel/traverse": "^7.7.0",
+        "@babel/types": "^7.7.0",
         "eslint-visitor-keys": "^1.0.0",
         "resolve": "^1.12.0"
       }
@@ -5022,15 +5073,81 @@
       }
     },
     "babel-loader": {
-      "version": "8.0.6",
-      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz",
-      "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz",
+      "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==",
       "dev": true,
       "requires": {
-        "find-cache-dir": "^2.0.0",
-        "loader-utils": "^1.0.2",
-        "mkdirp": "^0.5.1",
-        "pify": "^4.0.1"
+        "find-cache-dir": "^2.1.0",
+        "loader-utils": "^1.4.0",
+        "mkdirp": "^0.5.3",
+        "pify": "^4.0.1",
+        "schema-utils": "^2.6.5"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "6.12.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+          "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "emojis-list": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+          "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+          "dev": true
+        },
+        "fast-deep-equal": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+          "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+          "dev": true
+        },
+        "json5": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+          "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.0"
+          }
+        },
+        "loader-utils": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
+          "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
+          "dev": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^1.0.1"
+          }
+        },
+        "mkdirp": {
+          "version": "0.5.5",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+          "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.5"
+          }
+        },
+        "schema-utils": {
+          "version": "2.6.6",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+          "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.12.0",
+            "ajv-keywords": "^3.4.1"
+          }
+        }
       }
     },
     "babel-messages": {
@@ -5043,9 +5160,9 @@
       }
     },
     "babel-plugin-dynamic-import-node": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz",
-      "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==",
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+      "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
       "dev": true,
       "requires": {
         "object.assign": "^4.1.0"
@@ -5083,6 +5200,17 @@
         "pkg-up": "^3.1.0",
         "reselect": "^4.0.0",
         "resolve": "^1.13.1"
+      },
+      "dependencies": {
+        "pkg-up": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
+          "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
+          "dev": true,
+          "requires": {
+            "find-up": "^3.0.0"
+          }
+        }
       }
     },
     "babel-plugin-syntax-object-rest-spread": {
@@ -5357,6 +5485,30 @@
         "file-uri-to-path": "1.0.0"
       }
     },
+    "bl": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz",
+      "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==",
+      "dev": true,
+      "requires": {
+        "buffer": "^5.5.0",
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.4.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
     "block-stream": {
       "version": "0.0.9",
       "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -5626,14 +5778,15 @@
       }
     },
     "browserslist": {
-      "version": "4.8.7",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.7.tgz",
-      "integrity": "sha512-gFOnZNYBHrEyUML0xr5NJ6edFaaKbTFX9S9kQHlYfCP0Rit/boRIz4G+Avq6/4haEKJXdGGUnoolx+5MWW2BoA==",
+      "version": "4.12.0",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz",
+      "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==",
       "dev": true,
       "requires": {
-        "caniuse-lite": "^1.0.30001027",
-        "electron-to-chromium": "^1.3.349",
-        "node-releases": "^1.1.49"
+        "caniuse-lite": "^1.0.30001043",
+        "electron-to-chromium": "^1.3.413",
+        "node-releases": "^1.1.53",
+        "pkg-up": "^2.0.0"
       }
     },
     "bser": {
@@ -5646,14 +5799,13 @@
       }
     },
     "buffer": {
-      "version": "4.9.2",
-      "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
-      "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+      "version": "5.6.0",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
+      "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
       "dev": true,
       "requires": {
         "base64-js": "^1.0.2",
-        "ieee754": "^1.1.4",
-        "isarray": "^1.0.0"
+        "ieee754": "^1.1.4"
       }
     },
     "buffer-alloc": {
@@ -5938,9 +6090,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001028",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001028.tgz",
-      "integrity": "sha512-Vnrq+XMSHpT7E+LWoIYhs3Sne8h9lx9YJV3acH3THNCwU/9zV93/ta4xVfzTtnqd3rvnuVpVjE3DFqf56tr3aQ==",
+      "version": "1.0.30001051",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001051.tgz",
+      "integrity": "sha512-sw8UUnTlRevawTMZKN7vpfwSjCBVoiMPlYd8oT2VwNylyPCBdMAUmLGUApnYYTtIm5JXsQegUAY7GPHqgfDzjw==",
       "dev": true
     },
     "capture-exit": {
@@ -5981,9 +6133,9 @@
       }
     },
     "chalk": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
-      "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
+      "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
       "dev": true,
       "requires": {
         "ansi-styles": "^4.1.0",
@@ -6178,9 +6330,9 @@
       }
     },
     "cli-spinners": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.2.0.tgz",
-      "integrity": "sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.3.0.tgz",
+      "integrity": "sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w==",
       "dev": true
     },
     "cli-width": {
@@ -6190,60 +6342,53 @@
       "dev": true
     },
     "cliui": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
-      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+      "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+      "dev": true,
       "requires": {
-        "string-width": "^4.2.0",
-        "strip-ansi": "^6.0.0",
-        "wrap-ansi": "^6.2.0"
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1",
+        "wrap-ansi": "^2.0.0"
       },
       "dependencies": {
-        "ansi-styles": {
-          "version": "4.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
-          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
-          "requires": {
-            "@types/color-name": "^1.1.1",
-            "color-convert": "^2.0.1"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "color-name": {
-          "version": "1.1.4",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
-        },
         "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+          "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.0"
+          }
         },
         "string-width": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
-          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+          "dev": true,
           "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
+            "code-point-at": "^1.0.0",
+            "is-fullwidth-code-point": "^1.0.0",
+            "strip-ansi": "^3.0.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.0.0"
           }
         },
         "wrap-ansi": {
-          "version": "6.2.0",
-          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
-          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+          "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+          "dev": true,
           "requires": {
-            "ansi-styles": "^4.0.0",
-            "string-width": "^4.1.0",
-            "strip-ansi": "^6.0.0"
+            "string-width": "^1.0.1",
+            "strip-ansi": "^3.0.1"
           }
         }
       }
@@ -6483,6 +6628,35 @@
       "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
       "dev": true
     },
+    "compress-commons": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-3.0.0.tgz",
+      "integrity": "sha512-FyDqr8TKX5/X0qo+aVfaZ+PVmNJHJeckFBlq8jZGSJOgnynhfifoyl24qaqdUdDIBe0EVTHByN6NAkqYvE/2Xg==",
+      "dev": true,
+      "requires": {
+        "buffer-crc32": "^0.2.13",
+        "crc32-stream": "^3.0.1",
+        "normalize-path": "^3.0.0",
+        "readable-stream": "^2.3.7"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.3.7",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+          "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        }
+      }
+    },
     "compressible": {
       "version": "2.0.18",
       "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
@@ -6493,9 +6667,9 @@
       },
       "dependencies": {
         "mime-db": {
-          "version": "1.43.0",
-          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
-          "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
+          "version": "1.44.0",
+          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+          "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
           "dev": true
         }
       }
@@ -6547,13 +6721,13 @@
       },
       "dependencies": {
         "find-cache-dir": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz",
-          "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==",
+          "version": "3.3.1",
+          "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
+          "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
           "dev": true,
           "requires": {
             "commondir": "^1.0.1",
-            "make-dir": "^3.0.0",
+            "make-dir": "^3.0.2",
             "pkg-dir": "^4.1.0"
           }
         },
@@ -6577,9 +6751,9 @@
           }
         },
         "make-dir": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz",
-          "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==",
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
           "dev": true,
           "requires": {
             "semver": "^6.0.0"
@@ -7049,9 +7223,9 @@
       },
       "dependencies": {
         "cacache": {
-          "version": "12.0.3",
-          "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz",
-          "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
+          "version": "12.0.4",
+          "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+          "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
           "dev": true,
           "requires": {
             "bluebird": "^3.5.5",
@@ -7136,12 +7310,12 @@
       "dev": true
     },
     "core-js-compat": {
-      "version": "3.6.4",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz",
-      "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==",
+      "version": "3.6.5",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz",
+      "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==",
       "dev": true,
       "requires": {
-        "browserslist": "^4.8.3",
+        "browserslist": "^4.8.5",
         "semver": "7.0.0"
       },
       "dependencies": {
@@ -7154,9 +7328,9 @@
       }
     },
     "core-js-pure": {
-      "version": "3.6.4",
-      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz",
-      "integrity": "sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw==",
+      "version": "3.6.5",
+      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz",
+      "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==",
       "dev": true
     },
     "core-util-is": {
@@ -7195,6 +7369,29 @@
         }
       }
     },
+    "crc32-stream": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-3.0.1.tgz",
+      "integrity": "sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==",
+      "dev": true,
+      "requires": {
+        "crc": "^3.4.4",
+        "readable-stream": "^3.4.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
     "create-ecdh": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
@@ -7233,9 +7430,9 @@
       }
     },
     "cross-spawn": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz",
-      "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==",
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz",
+      "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==",
       "dev": true,
       "requires": {
         "path-key": "^3.1.0",
@@ -7330,9 +7527,9 @@
       }
     },
     "css-loader": {
-      "version": "3.4.2",
-      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.4.2.tgz",
-      "integrity": "sha512-jYq4zdZT0oS0Iykt+fqnzVLRIeiPWhka+7BqPn+oSIpWJAHak5tmB/WZrJ2a21JhCeFyNnnlroSl8c+MtVndzA==",
+      "version": "3.5.3",
+      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.3.tgz",
+      "integrity": "sha512-UEr9NH5Lmi7+dguAm+/JSPovNjYbm2k3TK58EiwQHzOHH5Jfq1Y+XoP2bQO6TMn7PptMd0opxxedAWcaSTRKHw==",
       "dev": true,
       "requires": {
         "camelcase": "^5.3.1",
@@ -7340,13 +7537,44 @@
         "icss-utils": "^4.1.1",
         "loader-utils": "^1.2.3",
         "normalize-path": "^3.0.0",
-        "postcss": "^7.0.23",
+        "postcss": "^7.0.27",
         "postcss-modules-extract-imports": "^2.0.0",
         "postcss-modules-local-by-default": "^3.0.2",
-        "postcss-modules-scope": "^2.1.1",
+        "postcss-modules-scope": "^2.2.0",
         "postcss-modules-values": "^3.0.0",
-        "postcss-value-parser": "^4.0.2",
-        "schema-utils": "^2.6.0"
+        "postcss-value-parser": "^4.0.3",
+        "schema-utils": "^2.6.6",
+        "semver": "^6.3.0"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "6.12.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+          "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "fast-deep-equal": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+          "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+          "dev": true
+        },
+        "schema-utils": {
+          "version": "2.6.6",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+          "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.12.0",
+            "ajv-keywords": "^3.4.1"
+          }
+        }
       }
     },
     "css-parse": {
@@ -7484,12 +7712,36 @@
       "dev": true
     },
     "csso": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.2.tgz",
-      "integrity": "sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz",
+      "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==",
       "dev": true,
       "requires": {
-        "css-tree": "1.0.0-alpha.37"
+        "css-tree": "1.0.0-alpha.39"
+      },
+      "dependencies": {
+        "css-tree": {
+          "version": "1.0.0-alpha.39",
+          "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz",
+          "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==",
+          "dev": true,
+          "requires": {
+            "mdn-data": "2.0.6",
+            "source-map": "^0.6.1"
+          }
+        },
+        "mdn-data": {
+          "version": "2.0.6",
+          "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz",
+          "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==",
+          "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
+        }
       }
     },
     "cssom": {
@@ -8122,14 +8374,22 @@
       "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA=="
     },
     "electron": {
-      "version": "8.2.0",
-      "resolved": "https://registry.npmjs.org/electron/-/electron-8.2.0.tgz",
-      "integrity": "sha512-mnV43gKCrCUMHLmGws/DU/l8LhaxrFD53A4ofwtthdCqOZWGIdk1+eMphiVumXR5a3lC64XVvmXQ2k28i7F/zw==",
+      "version": "8.2.5",
+      "resolved": "https://registry.npmjs.org/electron/-/electron-8.2.5.tgz",
+      "integrity": "sha512-LxSCUwmlfJtRwthd3ofpYaZ+1C2hQSW8Ep1DD9K3VbnDItO+kb3t1z35daJgAab78j54aOwo9gMxJtvU0Ftj6w==",
       "dev": true,
       "requires": {
         "@electron/get": "^1.0.1",
         "@types/node": "^12.0.12",
         "extract-zip": "^1.0.3"
+      },
+      "dependencies": {
+        "@types/node": {
+          "version": "12.12.37",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.37.tgz",
+          "integrity": "sha512-4mXKoDptrXAwZErQHrLzpe0FN/0Wmf5JRniSVIdwUrtDf9wnmEV1teCNLBo/TwuXhkK/bVegoEn/wmb+x0AuPg==",
+          "dev": true
+        }
       }
     },
     "electron-builder": {
@@ -8451,9 +8711,9 @@
       }
     },
     "electron-rebuild": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-1.10.0.tgz",
-      "integrity": "sha512-n10i30GJg7JH8yZL3ZY3x80YtKmSYuuN8cl+3Feljm+sQDU4rUW1jbnYGu0eUHlK3kPOiNWPtW7srGcwZ9p1zQ==",
+      "version": "1.10.1",
+      "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-1.10.1.tgz",
+      "integrity": "sha512-KSqp0Xiu7CCvKL2aEdPp/vNe2Rr11vaO8eM/wq9gQJTY02UjtAJ3l7WLV7Mf8oR+UJReJO8SWOWs/FozqK8ggA==",
       "dev": true,
       "requires": {
         "colors": "^1.3.3",
@@ -8544,9 +8804,9 @@
           }
         },
         "yargs": {
-          "version": "14.2.2",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.2.tgz",
-          "integrity": "sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA==",
+          "version": "14.2.3",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
+          "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
           "dev": true,
           "requires": {
             "cliui": "^5.0.0",
@@ -8559,13 +8819,13 @@
             "string-width": "^3.0.0",
             "which-module": "^2.0.0",
             "y18n": "^4.0.0",
-            "yargs-parser": "^15.0.0"
+            "yargs-parser": "^15.0.1"
           }
         },
         "yargs-parser": {
-          "version": "15.0.0",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
-          "integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
+          "version": "15.0.1",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
+          "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
           "dev": true,
           "requires": {
             "camelcase": "^5.0.0",
@@ -8575,9 +8835,9 @@
       }
     },
     "electron-to-chromium": {
-      "version": "1.3.356",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.356.tgz",
-      "integrity": "sha512-qW4YHMfOFjvx0jkSK2vjaHoLjk1+uJIV5tqtLDo7P5y3/kM8KQP23YBU0Y5fCSW4jIbDvEzeHDaY4+4vEaqqOw==",
+      "version": "1.3.428",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.428.tgz",
+      "integrity": "sha512-u3+5jEfgLKq/hGO96YfAoOAM1tgFnRDTCD5mLuev44tttcXix+INtVegAkmGzUcfDsnzkPt51XXurXZLLwXt0w==",
       "dev": true
     },
     "elementtree": {
@@ -9622,9 +9882,9 @@
       }
     },
     "express-session": {
-      "version": "1.17.0",
-      "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.0.tgz",
-      "integrity": "sha512-t4oX2z7uoSqATbMfsxWMbNjAL0T5zpvcJCk3Z9wnPPN7ibddhnmDZXHfEcoBMG2ojKXZoCyPMc5FbtK+G7SoDg==",
+      "version": "1.17.1",
+      "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz",
+      "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==",
       "requires": {
         "cookie": "0.4.0",
         "cookie-signature": "1.0.6",
@@ -9789,9 +10049,9 @@
           }
         },
         "mkdirp": {
-          "version": "0.5.4",
-          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
-          "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
+          "version": "0.5.5",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+          "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
           "dev": true,
           "requires": {
             "minimist": "^1.2.5"
@@ -9810,16 +10070,17 @@
       "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
     },
     "fast-glob": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz",
-      "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==",
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz",
+      "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==",
       "dev": true,
       "requires": {
         "@nodelib/fs.stat": "^2.0.2",
         "@nodelib/fs.walk": "^1.2.3",
         "glob-parent": "^5.1.0",
         "merge2": "^1.3.0",
-        "micromatch": "^4.0.2"
+        "micromatch": "^4.0.2",
+        "picomatch": "^2.2.1"
       }
     },
     "fast-json-stable-stringify": {
@@ -9844,12 +10105,12 @@
       "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
     },
     "fastq": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz",
-      "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==",
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.7.0.tgz",
+      "integrity": "sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ==",
       "dev": true,
       "requires": {
-        "reusify": "^1.0.0"
+        "reusify": "^1.0.4"
       }
     },
     "faye-websocket": {
@@ -9880,9 +10141,9 @@
       }
     },
     "figgy-pudding": {
-      "version": "3.5.1",
-      "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
-      "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==",
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
+      "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==",
       "dev": true
     },
     "figures": {
@@ -10158,17 +10419,160 @@
         "debug": "=3.1.0"
       }
     },
-    "for-in": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
-      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
-      "dev": true
-    },
-    "forever-agent": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
-    },
+    "for-in": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+      "dev": true
+    },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+    },
+    "fork-ts-checker-webpack-plugin": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.3.tgz",
+      "integrity": "sha512-ErA8cFsPfAIOx2UFoRlMraGVB1Ye3bXQTdNW6lmeKQDuNnkORqJmA9bcReNxJj5kVHeKkKcNZv3f6PMyeugO+w==",
+      "dev": true,
+      "requires": {
+        "babel-code-frame": "^6.22.0",
+        "chalk": "^2.4.1",
+        "micromatch": "^3.1.10",
+        "minimatch": "^3.0.4",
+        "semver": "^5.6.0",
+        "tapable": "^1.0.0",
+        "worker-rpc": "^0.1.0"
+      },
+      "dependencies": {
+        "braces": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+          "dev": true,
+          "requires": {
+            "arr-flatten": "^1.1.0",
+            "array-unique": "^0.3.2",
+            "extend-shallow": "^2.0.1",
+            "fill-range": "^4.0.0",
+            "isobject": "^3.0.1",
+            "repeat-element": "^1.1.2",
+            "snapdragon": "^0.8.1",
+            "snapdragon-node": "^2.0.1",
+            "split-string": "^3.0.2",
+            "to-regex": "^3.0.1"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "fill-range": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+          "dev": true,
+          "requires": {
+            "extend-shallow": "^2.0.1",
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1",
+            "to-regex-range": "^2.1.0"
+          },
+          "dependencies": {
+            "extend-shallow": {
+              "version": "2.0.1",
+              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+              "dev": true,
+              "requires": {
+                "is-extendable": "^0.1.0"
+              }
+            }
+          }
+        },
+        "is-buffer": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+          "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+          "dev": true
+        },
+        "is-number": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+          "dev": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          },
+          "dependencies": {
+            "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.5"
+              }
+            }
+          }
+        },
+        "micromatch": {
+          "version": "3.1.10",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+          "dev": true,
+          "requires": {
+            "arr-diff": "^4.0.0",
+            "array-unique": "^0.3.2",
+            "braces": "^2.3.1",
+            "define-property": "^2.0.2",
+            "extend-shallow": "^3.0.2",
+            "extglob": "^2.0.4",
+            "fragment-cache": "^0.2.1",
+            "kind-of": "^6.0.2",
+            "nanomatch": "^1.2.9",
+            "object.pick": "^1.3.0",
+            "regex-not": "^1.0.0",
+            "snapdragon": "^0.8.1",
+            "to-regex": "^3.0.2"
+          }
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
+        "to-regex-range": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+          "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+          "dev": true,
+          "requires": {
+            "is-number": "^3.0.0",
+            "repeat-string": "^1.6.1"
+          }
+        }
+      }
+    },
     "form-data": {
       "version": "2.3.3",
       "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
@@ -10255,6 +10659,12 @@
         "readable-stream": "^2.0.0"
       }
     },
+    "fs-constants": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+      "dev": true
+    },
     "fs-extra": {
       "version": "8.1.0",
       "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -10307,9 +10717,9 @@
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
     },
     "fsevents": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
-      "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+      "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
       "dev": true,
       "optional": true
     },
@@ -10602,9 +11012,9 @@
       }
     },
     "glob-parent": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
-      "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+      "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
       "dev": true,
       "requires": {
         "is-glob": "^4.0.1"
@@ -10764,9 +11174,9 @@
       }
     },
     "handle-thing": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
-      "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
+      "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
       "dev": true
     },
     "handlebars": {
@@ -10901,13 +11311,33 @@
       "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw=="
     },
     "hash-base": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
-      "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+      "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
       "dev": true,
       "requires": {
-        "inherits": "^2.0.1",
-        "safe-buffer": "^5.0.1"
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.6.0",
+        "safe-buffer": "^5.2.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+          "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
+          "dev": true
+        }
       }
     },
     "hash-sum": {
@@ -11006,9 +11436,9 @@
       }
     },
     "html-entities": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
-      "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz",
+      "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==",
       "dev": true
     },
     "html-escaper": {
@@ -11449,9 +11879,9 @@
       "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
     },
     "in-publish": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
-      "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz",
+      "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==",
       "dev": true
     },
     "indent-string": {
@@ -11492,49 +11922,79 @@
       "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
     },
     "inquirer": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.1.tgz",
-      "integrity": "sha512-V1FFQ3TIO15det8PijPLFR9M9baSlnRs9nL7zWu1MNVA2T9YVl9ZbrHJhYs7e9X8jeMZ3lr2JH/rdHFgNCBdYw==",
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz",
+      "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==",
       "dev": true,
       "requires": {
         "ansi-escapes": "^4.2.1",
-        "chalk": "^2.4.2",
+        "chalk": "^3.0.0",
         "cli-cursor": "^3.1.0",
         "cli-width": "^2.0.0",
         "external-editor": "^3.0.3",
         "figures": "^3.0.0",
         "lodash": "^4.17.15",
         "mute-stream": "0.0.8",
-        "run-async": "^2.2.0",
+        "run-async": "^2.4.0",
         "rxjs": "^6.5.3",
         "string-width": "^4.1.0",
-        "strip-ansi": "^5.1.0",
+        "strip-ansi": "^6.0.0",
         "through": "^2.3.6"
       },
       "dependencies": {
-        "ansi-regex": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
-          "dev": true
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
         },
         "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
           "dev": true,
           "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
           }
         },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
         "is-fullwidth-code-point": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
           "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
           "dev": true
         },
+        "run-async": {
+          "version": "2.4.1",
+          "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+          "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+          "dev": true
+        },
         "string-width": {
           "version": "4.2.0",
           "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
@@ -11544,34 +12004,15 @@
             "emoji-regex": "^8.0.0",
             "is-fullwidth-code-point": "^3.0.0",
             "strip-ansi": "^6.0.0"
-          },
-          "dependencies": {
-            "strip-ansi": {
-              "version": "6.0.0",
-              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
-              "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
-              "dev": true,
-              "requires": {
-                "ansi-regex": "^5.0.0"
-              }
-            }
           }
         },
-        "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
           "dev": true,
           "requires": {
-            "ansi-regex": "^4.1.0"
-          },
-          "dependencies": {
-            "ansi-regex": {
-              "version": "4.1.0",
-              "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-              "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-              "dev": true
-            }
+            "has-flag": "^4.0.0"
           }
         }
       }
@@ -11614,9 +12055,9 @@
       "dev": true
     },
     "ipaddr.js": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
-      "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==",
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
       "dev": true
     },
     "is-absolute-url": {
@@ -11972,10 +12413,13 @@
       "dev": true
     },
     "is-wsl": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz",
-      "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==",
-      "dev": true
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+      "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+      "dev": true,
+      "requires": {
+        "is-docker": "^2.0.0"
+      }
     },
     "is-yarn-global": {
       "version": "0.3.0",
@@ -13902,37 +14346,55 @@
       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
     },
     "jsdoc": {
-      "version": "3.6.3",
-      "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.3.tgz",
-      "integrity": "sha512-Yf1ZKA3r9nvtMWHO1kEuMZTlHOF8uoQ0vyo5eH7SQy5YeIiHM+B0DgKnn+X6y6KDYZcF7G2SPkKF+JORCXWE/A==",
+      "version": "3.6.4",
+      "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.4.tgz",
+      "integrity": "sha512-3G9d37VHv7MFdheviDCjUfQoIjdv4TC5zTTf5G9VODLtOnVS6La1eoYBDlbWfsRT3/Xo+j2MIqki2EV12BZfwA==",
       "dev": true,
       "requires": {
-        "@babel/parser": "^7.4.4",
-        "bluebird": "^3.5.4",
+        "@babel/parser": "^7.9.4",
+        "bluebird": "^3.7.2",
         "catharsis": "^0.8.11",
         "escape-string-regexp": "^2.0.0",
-        "js2xmlparser": "^4.0.0",
+        "js2xmlparser": "^4.0.1",
         "klaw": "^3.0.0",
-        "markdown-it": "^8.4.2",
-        "markdown-it-anchor": "^5.0.2",
-        "marked": "^0.7.0",
-        "mkdirp": "^0.5.1",
+        "markdown-it": "^10.0.0",
+        "markdown-it-anchor": "^5.2.7",
+        "marked": "^0.8.2",
+        "mkdirp": "^1.0.4",
         "requizzle": "^0.2.3",
-        "strip-json-comments": "^3.0.1",
+        "strip-json-comments": "^3.1.0",
         "taffydb": "2.6.2",
-        "underscore": "~1.9.1"
+        "underscore": "~1.10.2"
       },
       "dependencies": {
+        "@babel/parser": {
+          "version": "7.9.4",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz",
+          "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==",
+          "dev": true
+        },
         "escape-string-regexp": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
           "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
           "dev": true
         },
+        "marked": {
+          "version": "0.8.2",
+          "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz",
+          "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==",
+          "dev": true
+        },
+        "mkdirp": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+          "dev": true
+        },
         "strip-json-comments": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
-          "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz",
+          "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==",
           "dev": true
         }
       }
@@ -14257,6 +14719,15 @@
       "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.4.tgz",
       "integrity": "sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q=="
     },
+    "lazystream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
+      "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
+      "dev": true,
+      "requires": {
+        "readable-stream": "^2.0.5"
+      }
+    },
     "lcid": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
@@ -14507,18 +14978,42 @@
       "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
       "dev": true
     },
+    "lodash.defaults": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+      "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=",
+      "dev": true
+    },
+    "lodash.difference": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
+      "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=",
+      "dev": true
+    },
     "lodash.findkey": {
       "version": "4.6.0",
       "resolved": "https://registry.npmjs.org/lodash.findkey/-/lodash.findkey-4.6.0.tgz",
       "integrity": "sha1-gwWOkDtRy7dZ0JzPVG3qPqOcRxg=",
       "dev": true
     },
+    "lodash.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+      "dev": true
+    },
     "lodash.get": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
       "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
       "dev": true
     },
+    "lodash.isplainobject": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+      "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
+      "dev": true
+    },
     "lodash.kebabcase": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
@@ -14586,6 +15081,12 @@
       "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=",
       "dev": true
     },
+    "lodash.union": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
+      "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=",
+      "dev": true
+    },
     "lodash.uniq": {
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -14615,62 +15116,93 @@
       }
     },
     "log-update": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/log-update/-/log-update-3.3.0.tgz",
-      "integrity": "sha512-YSKm5n+YjZoGZT5lfmOqasVH1fIH9xQA9A81Y48nZ99PxAP62vdCCtua+Gcu6oTn0nqtZd/LwRV+Vflo53ZDWA==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+      "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
       "dev": true,
       "requires": {
-        "ansi-escapes": "^3.2.0",
-        "cli-cursor": "^2.1.0",
-        "wrap-ansi": "^5.0.0"
+        "ansi-escapes": "^4.3.0",
+        "cli-cursor": "^3.1.0",
+        "slice-ansi": "^4.0.0",
+        "wrap-ansi": "^6.2.0"
       },
       "dependencies": {
-        "ansi-escapes": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
-          "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "astral-regex": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+          "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
           "dev": true
         },
-        "cli-cursor": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
-          "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
           "dev": true,
           "requires": {
-            "restore-cursor": "^2.0.0"
+            "color-name": "~1.1.4"
           }
         },
-        "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==",
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "onetime": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
-          "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+          "dev": true
+        },
+        "slice-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+          "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
           "dev": true,
           "requires": {
-            "mimic-fn": "^1.0.0"
+            "ansi-styles": "^4.0.0",
+            "astral-regex": "^2.0.0",
+            "is-fullwidth-code-point": "^3.0.0"
           }
         },
-        "restore-cursor": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
-          "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+        "string-width": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
           "dev": true,
           "requires": {
-            "onetime": "^2.0.0",
-            "signal-exit": "^3.0.2"
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.0"
+          }
+        },
+        "wrap-ansi": {
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
           }
         }
       }
     },
     "loglevel": {
-      "version": "1.6.7",
-      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.7.tgz",
-      "integrity": "sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A==",
+      "version": "1.6.8",
+      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
+      "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==",
       "dev": true
     },
     "loose-envify": {
@@ -14747,12 +15279,6 @@
         "tmpl": "1.0.x"
       }
     },
-    "mamacro": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz",
-      "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==",
-      "dev": true
-    },
     "map-age-cleaner": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
@@ -14784,30 +15310,22 @@
       }
     },
     "markdown-it": {
-      "version": "8.4.2",
-      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz",
-      "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==",
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
+      "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
       "dev": true,
       "requires": {
         "argparse": "^1.0.7",
-        "entities": "~1.1.1",
+        "entities": "~2.0.0",
         "linkify-it": "^2.0.0",
         "mdurl": "^1.0.1",
         "uc.micro": "^1.0.5"
-      },
-      "dependencies": {
-        "entities": {
-          "version": "1.1.2",
-          "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
-          "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
-          "dev": true
-        }
       }
     },
     "markdown-it-anchor": {
-      "version": "5.2.5",
-      "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz",
-      "integrity": "sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ==",
+      "version": "5.2.7",
+      "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.7.tgz",
+      "integrity": "sha512-REFmIaSS6szaD1bye80DMbp7ePwsPNvLTR5HunsUcZ0SG0rWJQ+Pz24R4UlTKtjKBPhxo0v0tOBDYjZQQknW8Q==",
       "dev": true
     },
     "marked": {
@@ -14941,6 +15459,12 @@
       "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
       "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
     },
+    "microevent.ts": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz",
+      "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==",
+      "dev": true
+    },
     "micromatch": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
@@ -15172,6 +15696,12 @@
       "integrity": "sha512-Q2PKB4ZR4UPtjLl76JfzlgSCUZhSV1AXQgAZa1qt5RiaALFjP/CDrGvFBrOz7Ck6McPcwMAxTsJvWOUjOU8XMw==",
       "dev": true
     },
+    "moment": {
+      "version": "2.25.3",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz",
+      "integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg==",
+      "dev": true
+    },
     "move-concurrently": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -15295,9 +15825,9 @@
       }
     },
     "node-abi": {
-      "version": "2.15.0",
-      "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.15.0.tgz",
-      "integrity": "sha512-FeLpTS0F39U7hHZU1srAK4Vx+5AHNVOTP+hxBNQknR/54laTHSFIJkDWDqiquY1LeLUgTfPN7sLPhMubx0PLAg==",
+      "version": "2.16.0",
+      "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.16.0.tgz",
+      "integrity": "sha512-+sa0XNlWDA6T+bDLmkCUYn6W5k5W6BPRL6mqzSCs6H/xUgtl4D5x2fORKDzopKiU6wsyn/+wXlRXwXeSp+mtoA==",
       "requires": {
         "semver": "^5.4.1"
       },
@@ -15395,6 +15925,17 @@
         "vm-browserify": "^1.0.1"
       },
       "dependencies": {
+        "buffer": {
+          "version": "4.9.2",
+          "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+          "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+          "dev": true,
+          "requires": {
+            "base64-js": "^1.0.2",
+            "ieee754": "^1.1.4",
+            "isarray": "^1.0.0"
+          }
+        },
         "punycode": {
           "version": "1.4.1",
           "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
@@ -15521,18 +16062,15 @@
       }
     },
     "node-releases": {
-      "version": "1.1.49",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.49.tgz",
-      "integrity": "sha512-xH8t0LS0disN0mtRCh+eByxFPie+msJUBL/lJDBuap53QGiYPa9joh83K4pCZgWJ+2L4b9h88vCVdXQ60NO2bg==",
-      "dev": true,
-      "requires": {
-        "semver": "^6.3.0"
-      }
+      "version": "1.1.54",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.54.tgz",
+      "integrity": "sha512-tLzytKpgwKQr37yw9CEODjNM9lnmsNxzlv575GzOZ16AgMvPcJis/DgrJX4UEV1KIYoXk6XoVfY6YaMOPJESAQ==",
+      "dev": true
     },
     "node-sass": {
-      "version": "4.13.1",
-      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz",
-      "integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==",
+      "version": "4.14.0",
+      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.0.tgz",
+      "integrity": "sha512-AxqU+DFpk0lEz95sI6jO0hU0Rwyw7BXVEv6o9OItoXLyeygPeaSpiV4rwQb10JiTghHaa0gZeD21sz+OsQluaw==",
       "dev": true,
       "requires": {
         "async-foreach": "^0.1.3",
@@ -15877,10 +16415,72 @@
       "dev": true
     },
     "object-is": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz",
-      "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==",
-      "dev": true
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz",
+      "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.5"
+      },
+      "dependencies": {
+        "es-abstract": {
+          "version": "1.17.5",
+          "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
+          "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+          "dev": true,
+          "requires": {
+            "es-to-primitive": "^1.2.1",
+            "function-bind": "^1.1.1",
+            "has": "^1.0.3",
+            "has-symbols": "^1.0.1",
+            "is-callable": "^1.1.5",
+            "is-regex": "^1.0.5",
+            "object-inspect": "^1.7.0",
+            "object-keys": "^1.1.1",
+            "object.assign": "^4.1.0",
+            "string.prototype.trimleft": "^2.1.1",
+            "string.prototype.trimright": "^2.1.1"
+          }
+        },
+        "is-callable": {
+          "version": "1.1.5",
+          "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
+          "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
+          "dev": true
+        },
+        "is-regex": {
+          "version": "1.0.5",
+          "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
+          "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+          "dev": true,
+          "requires": {
+            "has": "^1.0.3"
+          }
+        },
+        "string.prototype.trimleft": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
+          "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
+          "dev": true,
+          "requires": {
+            "define-properties": "^1.1.3",
+            "es-abstract": "^1.17.5",
+            "string.prototype.trimstart": "^1.0.0"
+          }
+        },
+        "string.prototype.trimright": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
+          "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
+          "dev": true,
+          "requires": {
+            "define-properties": "^1.1.3",
+            "es-abstract": "^1.17.5",
+            "string.prototype.trimend": "^1.0.0"
+          }
+        }
+      }
     },
     "object-keys": {
       "version": "1.1.1",
@@ -15983,9 +16583,9 @@
       }
     },
     "open": {
-      "version": "7.0.2",
-      "resolved": "https://registry.npmjs.org/open/-/open-7.0.2.tgz",
-      "integrity": "sha512-70E/pFTPr7nZ9nLDPNTcj3IVqnNvKuP4VsBmoKV9YGTnChe0mlS3C4qM7qKarhZ8rGaHKLfo+vBTHXDp6ZSyLQ==",
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/open/-/open-7.0.3.tgz",
+      "integrity": "sha512-sP2ru2v0P290WFfv49Ap8MF6PkzGNnGlAwHweB4WR4mr5d2d0woiCluUeJ218w7/+PmoBy9JmYgD5A4mLcWOFA==",
       "dev": true,
       "requires": {
         "is-docker": "^2.0.0",
@@ -16474,9 +17074,9 @@
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
     },
     "picomatch": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz",
-      "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==",
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+      "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
       "dev": true
     },
     "pify": {
@@ -16501,9 +17101,9 @@
       }
     },
     "pino": {
-      "version": "5.16.0",
-      "resolved": "https://registry.npmjs.org/pino/-/pino-5.16.0.tgz",
-      "integrity": "sha512-k9cDzHd9S/oYSQ9B9g9+7RXkfsZX78sQXERC8x4p2XArECZXULx9nqNwZvJHsLj779wPCt+ybN+dG8jFR70p6Q==",
+      "version": "5.17.0",
+      "resolved": "https://registry.npmjs.org/pino/-/pino-5.17.0.tgz",
+      "integrity": "sha512-LqrqmRcJz8etUjyV0ddqB6OTUutCgQULPFg2b4dtijRHUsucaAdBgSUW58vY6RFSX+NT8963F+q0tM6lNwGShA==",
       "requires": {
         "fast-redact": "^2.0.0",
         "fast-safe-stringify": "^2.0.7",
@@ -16537,12 +17137,57 @@
       }
     },
     "pkg-up": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
-      "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
+      "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
       "dev": true,
       "requires": {
-        "find-up": "^3.0.0"
+        "find-up": "^2.1.0"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+          "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+          "dev": true,
+          "requires": {
+            "locate-path": "^2.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+          "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+          "dev": true,
+          "requires": {
+            "p-locate": "^2.0.0",
+            "path-exists": "^3.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+          "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+          "dev": true,
+          "requires": {
+            "p-try": "^1.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+          "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+          "dev": true,
+          "requires": {
+            "p-limit": "^1.1.0"
+          }
+        },
+        "p-try": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+          "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+          "dev": true
+        }
       }
     },
     "plist": {
@@ -16562,9 +17207,9 @@
       "dev": true
     },
     "portfinder": {
-      "version": "1.0.25",
-      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
-      "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==",
+      "version": "1.0.26",
+      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz",
+      "integrity": "sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==",
       "dev": true,
       "requires": {
         "async": "^2.6.2",
@@ -16596,9 +17241,9 @@
       "dev": true
     },
     "postcss": {
-      "version": "7.0.27",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz",
-      "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==",
+      "version": "7.0.29",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz",
+      "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==",
       "dev": true,
       "requires": {
         "chalk": "^2.4.2",
@@ -16920,9 +17565,9 @@
       }
     },
     "postcss-modules-scope": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.1.tgz",
-      "integrity": "sha512-OXRUPecnHCg8b9xWvldG/jUpRIGPNRka0r4D4j0ESUU2/5IOnpsjfPPmDprM3Ih8CgZ8FXjWqaniK5v4rWt3oQ==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz",
+      "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==",
       "dev": true,
       "requires": {
         "postcss": "^7.0.6",
@@ -17154,12 +17799,12 @@
       }
     },
     "postcss-rtl": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/postcss-rtl/-/postcss-rtl-1.5.0.tgz",
-      "integrity": "sha512-7uQeaMBhAlnu7xgytvTocojFKp08W4FND/xE/ajj/J6ABOGhdDF1mLGzaRrC5/u/Sr71BEUi13xgvs2j8U16AA==",
+      "version": "1.7.3",
+      "resolved": "https://registry.npmjs.org/postcss-rtl/-/postcss-rtl-1.7.3.tgz",
+      "integrity": "sha512-PMwlrQSeZKChNJQGtWz9Xfk3rY1W7P5Jp4sFRXVufczQIH6vRhTNSc5gnEwKHaWrU8SMoZMi2VY7ihOmwVvW7g==",
       "dev": true,
       "requires": {
-        "rtlcss": "^2.4.0"
+        "rtlcss": "2.5.0"
       }
     },
     "postcss-safe-parser": {
@@ -17214,9 +17859,9 @@
       }
     },
     "postcss-value-parser": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz",
-      "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
+      "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
       "dev": true
     },
     "prelude-ls": {
@@ -17235,7 +17880,8 @@
       "version": "1.19.1",
       "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
       "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
-      "dev": true
+      "dev": true,
+      "optional": true
     },
     "pretty": {
       "version": "2.0.0",
@@ -17449,9 +18095,9 @@
       "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
     },
     "quasar": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/quasar/-/quasar-1.9.3.tgz",
-      "integrity": "sha512-wmxeaNYTGXBFDReJT1MkOR29thlDrNwrnMjDUXLeOwfmhZBqRl2gDCn1/7v6Ri3fvM1pjF7yUnJkhlcGrHFgmw=="
+      "version": "1.10.5",
+      "resolved": "https://registry.npmjs.org/quasar/-/quasar-1.10.5.tgz",
+      "integrity": "sha512-Y6wrOWWySEIQENorvWxVPph7McZxuZZdBVppq/4SWcazTkwfOiiPKDDANqk79wlD6+6Fw4pmnKW//T8koFHDsQ=="
     },
     "query-string": {
       "version": "4.3.4",
@@ -17827,9 +18473,9 @@
       "dev": true
     },
     "regenerate-unicode-properties": {
-      "version": "8.1.0",
-      "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz",
-      "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==",
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz",
+      "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==",
       "dev": true,
       "requires": {
         "regenerate": "^1.4.0"
@@ -17842,12 +18488,13 @@
       "dev": true
     },
     "regenerator-transform": {
-      "version": "0.14.1",
-      "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz",
-      "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==",
+      "version": "0.14.4",
+      "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz",
+      "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==",
       "dev": true,
       "requires": {
-        "private": "^0.1.6"
+        "@babel/runtime": "^7.8.4",
+        "private": "^0.1.8"
       }
     },
     "regex-not": {
@@ -17877,23 +18524,23 @@
       "dev": true
     },
     "regexpu-core": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz",
-      "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==",
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz",
+      "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==",
       "dev": true,
       "requires": {
         "regenerate": "^1.4.0",
-        "regenerate-unicode-properties": "^8.1.0",
-        "regjsgen": "^0.5.0",
-        "regjsparser": "^0.6.0",
+        "regenerate-unicode-properties": "^8.2.0",
+        "regjsgen": "^0.5.1",
+        "regjsparser": "^0.6.4",
         "unicode-match-property-ecmascript": "^1.0.4",
-        "unicode-match-property-value-ecmascript": "^1.1.0"
+        "unicode-match-property-value-ecmascript": "^1.2.0"
       }
     },
     "register-service-worker": {
-      "version": "1.6.2",
-      "resolved": "https://registry.npmjs.org/register-service-worker/-/register-service-worker-1.6.2.tgz",
-      "integrity": "sha512-I8L87fX2TK29LDx+wgyOUh2BJ3rDIRC1FtRZEHeP3rivzDv6p1DDZLGGtPucqjEkm45+2crtFIFssEWv56+9Wg==",
+      "version": "1.7.1",
+      "resolved": "https://registry.npmjs.org/register-service-worker/-/register-service-worker-1.7.1.tgz",
+      "integrity": "sha512-IdTfUZ4u8iJL8o1w8es8l6UMGPmkwHolUdT+UmM1UypC80IB4KbpuIlvwWVj8UDS7eJwkEYRcKRgfRX+oTmJsw==",
       "dev": true
     },
     "registry-auth-token": {
@@ -17919,9 +18566,9 @@
       "dev": true
     },
     "regjsparser": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.3.tgz",
-      "integrity": "sha512-8uZvYbnfAtEm9Ab8NTb3hdLwL4g/LQzEYP7Xs27T96abJCCE2d6r3cPZPQEsLKy0vRSGVNG+/zVGtLr86HQduA==",
+      "version": "0.6.4",
+      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz",
+      "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==",
       "dev": true,
       "requires": {
         "jsesc": "~0.5.0"
@@ -18482,9 +19129,9 @@
       }
     },
     "sass-graph": {
-      "version": "2.2.4",
-      "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
-      "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
+      "version": "2.2.6",
+      "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.6.tgz",
+      "integrity": "sha512-MKuEYXFSGuRSi8FZ3A7imN1CeVn9Gpw0/SFJKdL1ejXJneI9a5rwlEZrKejhEFAA3O6yr3eIyl/WuvASvlT36g==",
       "dev": true,
       "requires": {
         "glob": "^7.0.0",
@@ -18499,17 +19146,6 @@
           "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
           "dev": true
         },
-        "cliui": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
-          "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
-          "dev": true,
-          "requires": {
-            "string-width": "^1.0.1",
-            "strip-ansi": "^3.0.1",
-            "wrap-ansi": "^2.0.0"
-          }
-        },
         "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",
@@ -18545,16 +19181,6 @@
           "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
           "dev": true
         },
-        "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.1",
-            "strip-ansi": "^3.0.1"
-          }
-        },
         "y18n": {
           "version": "3.2.1",
           "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
@@ -19118,10 +19744,11 @@
       }
     },
     "sonic-boom": {
-      "version": "0.7.6",
-      "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-0.7.6.tgz",
-      "integrity": "sha512-k9E2QQ4zxuVRLDW+ZW6ISzJs3wlEorVdmM7ApDgor7wsGKSDG5YGHsGmgLY4XYh4DMlr/2ap2BWAE7yTFJtWnQ==",
+      "version": "0.7.7",
+      "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-0.7.7.tgz",
+      "integrity": "sha512-Ei5YOo5J64GKClHIL/5evJPgASXFVpfVYbJV9PILZQytTK6/LCwHvsZJW2Ig4p9FMC2OrBrMnXKgRN/OEoAWfg==",
       "requires": {
+        "atomic-sleep": "^1.0.0",
         "flatstr": "^1.0.12"
       }
     },
@@ -19288,9 +19915,9 @@
       }
     },
     "spdy": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz",
-      "integrity": "sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==",
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+      "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
       "dev": true,
       "requires": {
         "debug": "^4.1.0",
@@ -19374,32 +20001,14 @@
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
     },
     "sqlite3": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz",
-      "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==",
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz",
+      "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==",
       "requires": {
         "nan": "^2.12.1",
-        "node-pre-gyp": "^0.11.0",
-        "request": "^2.87.0"
+        "node-pre-gyp": "^0.11.0"
       },
       "dependencies": {
-        "fs-minipass": {
-          "version": "1.2.7",
-          "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
-          "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
-          "requires": {
-            "minipass": "^2.6.0"
-          }
-        },
-        "minipass": {
-          "version": "2.9.0",
-          "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
-          "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
-          "requires": {
-            "safe-buffer": "^5.1.2",
-            "yallist": "^3.0.0"
-          }
-        },
         "node-pre-gyp": {
           "version": "0.11.0",
           "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz",
@@ -19417,38 +20026,10 @@
             "tar": "^4"
           }
         },
-        "nopt": {
-          "version": "4.0.1",
-          "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
-          "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
-          "requires": {
-            "abbrev": "1",
-            "osenv": "^0.1.4"
-          }
-        },
         "semver": {
           "version": "5.7.1",
           "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
           "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
-        },
-        "tar": {
-          "version": "4.4.13",
-          "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
-          "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
-          "requires": {
-            "chownr": "^1.1.1",
-            "fs-minipass": "^1.2.5",
-            "minipass": "^2.8.6",
-            "minizlib": "^1.2.1",
-            "mkdirp": "^0.5.0",
-            "safe-buffer": "^5.1.2",
-            "yallist": "^3.0.3"
-          }
-        },
-        "yallist": {
-          "version": "3.1.1",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-          "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
         }
       }
     },
@@ -19664,6 +20245,74 @@
         }
       }
     },
+    "string.prototype.trimend": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
+      "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.5"
+      },
+      "dependencies": {
+        "es-abstract": {
+          "version": "1.17.5",
+          "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
+          "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+          "dev": true,
+          "requires": {
+            "es-to-primitive": "^1.2.1",
+            "function-bind": "^1.1.1",
+            "has": "^1.0.3",
+            "has-symbols": "^1.0.1",
+            "is-callable": "^1.1.5",
+            "is-regex": "^1.0.5",
+            "object-inspect": "^1.7.0",
+            "object-keys": "^1.1.1",
+            "object.assign": "^4.1.0",
+            "string.prototype.trimleft": "^2.1.1",
+            "string.prototype.trimright": "^2.1.1"
+          }
+        },
+        "is-callable": {
+          "version": "1.1.5",
+          "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
+          "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
+          "dev": true
+        },
+        "is-regex": {
+          "version": "1.0.5",
+          "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
+          "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+          "dev": true,
+          "requires": {
+            "has": "^1.0.3"
+          }
+        },
+        "string.prototype.trimleft": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
+          "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
+          "dev": true,
+          "requires": {
+            "define-properties": "^1.1.3",
+            "es-abstract": "^1.17.5",
+            "string.prototype.trimstart": "^1.0.0"
+          }
+        },
+        "string.prototype.trimright": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
+          "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
+          "dev": true,
+          "requires": {
+            "define-properties": "^1.1.3",
+            "es-abstract": "^1.17.5",
+            "string.prototype.trimend": "^1.0.0"
+          }
+        }
+      }
+    },
     "string.prototype.trimleft": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz",
@@ -19684,6 +20333,74 @@
         "function-bind": "^1.1.1"
       }
     },
+    "string.prototype.trimstart": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
+      "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.5"
+      },
+      "dependencies": {
+        "es-abstract": {
+          "version": "1.17.5",
+          "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
+          "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+          "dev": true,
+          "requires": {
+            "es-to-primitive": "^1.2.1",
+            "function-bind": "^1.1.1",
+            "has": "^1.0.3",
+            "has-symbols": "^1.0.1",
+            "is-callable": "^1.1.5",
+            "is-regex": "^1.0.5",
+            "object-inspect": "^1.7.0",
+            "object-keys": "^1.1.1",
+            "object.assign": "^4.1.0",
+            "string.prototype.trimleft": "^2.1.1",
+            "string.prototype.trimright": "^2.1.1"
+          }
+        },
+        "is-callable": {
+          "version": "1.1.5",
+          "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
+          "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
+          "dev": true
+        },
+        "is-regex": {
+          "version": "1.0.5",
+          "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
+          "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+          "dev": true,
+          "requires": {
+            "has": "^1.0.3"
+          }
+        },
+        "string.prototype.trimleft": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
+          "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
+          "dev": true,
+          "requires": {
+            "define-properties": "^1.1.3",
+            "es-abstract": "^1.17.5",
+            "string.prototype.trimstart": "^1.0.0"
+          }
+        },
+        "string.prototype.trimright": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
+          "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
+          "dev": true,
+          "requires": {
+            "define-properties": "^1.1.3",
+            "es-abstract": "^1.17.5",
+            "string.prototype.trimend": "^1.0.0"
+          }
+        }
+      }
+    },
     "string_decoder": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -20009,6 +20726,32 @@
         }
       }
     },
+    "tar-stream": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz",
+      "integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==",
+      "dev": true,
+      "requires": {
+        "bl": "^4.0.1",
+        "end-of-stream": "^1.4.1",
+        "fs-constants": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^3.1.1"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
     "temp-file": {
       "version": "3.3.6",
       "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.3.6.tgz",
@@ -20099,9 +20842,9 @@
       }
     },
     "terser": {
-      "version": "4.6.3",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz",
-      "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==",
+      "version": "4.6.13",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.13.tgz",
+      "integrity": "sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw==",
       "dev": true,
       "requires": {
         "commander": "^2.20.0",
@@ -20118,30 +20861,48 @@
       }
     },
     "terser-webpack-plugin": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.4.tgz",
-      "integrity": "sha512-Nv96Nws2R2nrFOpbzF6IxRDpIkkIfmhvOws+IqMvYdFLO7o6wAILWFKONFgaYy8+T4LVz77DQW0f7wOeDEAjrg==",
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.6.tgz",
+      "integrity": "sha512-I8IDsQwZrqjdmOicNeE8L/MhwatAap3mUrtcAKJuilsemUNcX+Hier/eAzwStVqhlCxq0aG3ni9bK/0BESXkTg==",
       "dev": true,
       "requires": {
         "cacache": "^13.0.1",
-        "find-cache-dir": "^3.2.0",
-        "jest-worker": "^25.1.0",
-        "p-limit": "^2.2.2",
-        "schema-utils": "^2.6.4",
-        "serialize-javascript": "^2.1.2",
+        "find-cache-dir": "^3.3.1",
+        "jest-worker": "^25.4.0",
+        "p-limit": "^2.3.0",
+        "schema-utils": "^2.6.6",
+        "serialize-javascript": "^3.0.0",
         "source-map": "^0.6.1",
-        "terser": "^4.4.3",
+        "terser": "^4.6.12",
         "webpack-sources": "^1.4.3"
       },
       "dependencies": {
+        "ajv": {
+          "version": "6.12.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+          "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "fast-deep-equal": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+          "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+          "dev": true
+        },
         "find-cache-dir": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz",
-          "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==",
+          "version": "3.3.1",
+          "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
+          "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
           "dev": true,
           "requires": {
             "commondir": "^1.0.1",
-            "make-dir": "^3.0.0",
+            "make-dir": "^3.0.2",
             "pkg-dir": "^4.1.0"
           }
         },
@@ -20162,9 +20923,9 @@
           "dev": true
         },
         "jest-worker": {
-          "version": "25.1.0",
-          "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz",
-          "integrity": "sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg==",
+          "version": "25.5.0",
+          "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz",
+          "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==",
           "dev": true,
           "requires": {
             "merge-stream": "^2.0.0",
@@ -20181,18 +20942,18 @@
           }
         },
         "make-dir": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz",
-          "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==",
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
           "dev": true,
           "requires": {
             "semver": "^6.0.0"
           }
         },
         "p-limit": {
-          "version": "2.2.2",
-          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
-          "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
           "dev": true,
           "requires": {
             "p-try": "^2.0.0"
@@ -20222,6 +20983,22 @@
             "find-up": "^4.0.0"
           }
         },
+        "schema-utils": {
+          "version": "2.6.6",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+          "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.12.0",
+            "ajv-keywords": "^3.4.1"
+          }
+        },
+        "serialize-javascript": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.0.0.tgz",
+          "integrity": "sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw==",
+          "dev": true
+        },
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -20551,6 +21328,32 @@
       "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
       "dev": true
     },
+    "ts-loader": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-7.0.1.tgz",
+      "integrity": "sha512-wdGs9xO8UnwASwbluehzXciBtc9HfGlYA8Aiv856etLmdv8mJfAxCkt3YpS4g7G1IsGxaCVKQ102Qh0zycpeZQ==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.3.0",
+        "enhanced-resolve": "^4.0.0",
+        "loader-utils": "^1.0.2",
+        "micromatch": "^4.0.0",
+        "semver": "^6.0.0"
+      },
+      "dependencies": {
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        }
+      }
+    },
     "tsconfig": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
@@ -20622,7 +21425,8 @@
       "version": "0.8.1",
       "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
       "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
-      "dev": true
+      "dev": true,
+      "optional": true
     },
     "type-is": {
       "version": "1.6.18",
@@ -20639,6 +21443,12 @@
       "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
       "dev": true
     },
+    "typescript": {
+      "version": "3.8.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
+      "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==",
+      "dev": true
+    },
     "typical": {
       "version": "2.6.1",
       "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz",
@@ -20678,9 +21488,9 @@
       }
     },
     "underscore": {
-      "version": "1.9.2",
-      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz",
-      "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==",
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz",
+      "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==",
       "dev": true
     },
     "unicode-canonical-property-names-ecmascript": {
@@ -20700,15 +21510,15 @@
       }
     },
     "unicode-match-property-value-ecmascript": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz",
-      "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz",
+      "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==",
       "dev": true
     },
     "unicode-property-aliases-ecmascript": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz",
-      "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz",
+      "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==",
       "dev": true
     },
     "union-value": {
@@ -20893,21 +21703,84 @@
       }
     },
     "url-loader": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-3.0.0.tgz",
-      "integrity": "sha512-a84JJbIA5xTFTWyjjcPdnsu+41o/SNE8SpXMdUvXs6Q+LuhCD9E2+0VCiuDWqgo3GGXVlFHzArDmBpj9PgWn4A==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.0.tgz",
+      "integrity": "sha512-IzgAAIC8wRrg6NYkFIJY09vtktQcsvU8V6HhtQj9PTefbYImzLB1hufqo4m+RyM5N3mLx5BqJKccgxJS+W3kqw==",
       "dev": true,
       "requires": {
-        "loader-utils": "^1.2.3",
-        "mime": "^2.4.4",
-        "schema-utils": "^2.5.0"
+        "loader-utils": "^2.0.0",
+        "mime-types": "^2.1.26",
+        "schema-utils": "^2.6.5"
       },
       "dependencies": {
-        "mime": {
-          "version": "2.4.4",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
-          "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+        "ajv": {
+          "version": "6.12.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+          "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "emojis-list": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+          "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+          "dev": true
+        },
+        "fast-deep-equal": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+          "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+          "dev": true
+        },
+        "json5": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+          "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.5"
+          }
+        },
+        "loader-utils": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+          "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+          "dev": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
+        "mime-db": {
+          "version": "1.44.0",
+          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+          "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
           "dev": true
+        },
+        "mime-types": {
+          "version": "2.1.27",
+          "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+          "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+          "dev": true,
+          "requires": {
+            "mime-db": "1.44.0"
+          }
+        },
+        "schema-utils": {
+          "version": "2.6.6",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+          "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.12.0",
+            "ajv-keywords": "^3.4.1"
+          }
         }
       }
     },
@@ -21123,9 +21996,9 @@
       }
     },
     "vue-loader": {
-      "version": "15.9.0",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.0.tgz",
-      "integrity": "sha512-FeDHvTSpwyLeF7LIV1PYkvqUQgTJ8UmOxhSlCyRSxaXCKk+M6NF4tDQsLsPPNeDPyR7TfRQ8MLg6v+8PsDV9xQ==",
+      "version": "15.9.1",
+      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.1.tgz",
+      "integrity": "sha512-IaPU2KOPjs/QjMlxFs/TiTtQUSbftQ7lsAvoxe21rtcQohsMhx+1AltXCNhZIpIn46PtODiAgz+o8RbMpKtmJw==",
       "dev": true,
       "requires": {
         "@vue/component-compiler-utils": "^3.1.0",
@@ -21136,9 +22009,9 @@
       }
     },
     "vue-router": {
-      "version": "3.1.5",
-      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.1.5.tgz",
-      "integrity": "sha512-BszkPvhl7I9h334GjckCh7sVFyjTPMMJFJ4Bsrem/Ik+B/9gt5tgrk8k4gGLO4ZpdvciVdg7O41gW4DisQWurg==",
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.1.6.tgz",
+      "integrity": "sha512-GYhn2ynaZlysZMkFE5oCHRUTqE8BWs/a9YbKpNLi0i7xD6KG1EzDqpHQmv1F5gXjr8kL5iIVS8EOtRaVUEXTqA==",
       "dev": true
     },
     "vue-server-renderer": {
@@ -21226,9 +22099,9 @@
       "dev": true
     },
     "vuex": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.2.tgz",
-      "integrity": "sha512-ha3jNLJqNhhrAemDXcmMJMKf1Zu4sybMPr9KxJIuOpVcsDQlTBYLLladav2U+g1AvdYDG5Gs0xBTb0M5pXXYFQ==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.3.0.tgz",
+      "integrity": "sha512-1MfcBt+YFd20DPwKe0ThhYm1UEXZya4gVKUvCy7AtS11YAOUR+9a6u4fsv1Rr6ePZCDNxW/M1zuIaswp6nNv8Q==",
       "dev": true
     },
     "w3c-hr-time": {
@@ -21256,12 +22129,12 @@
       }
     },
     "watchpack": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
-      "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz",
+      "integrity": "sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA==",
       "dev": true,
       "requires": {
-        "chokidar": "^2.0.2",
+        "chokidar": "^2.1.8",
         "graceful-fs": "^4.1.2",
         "neo-async": "^2.5.0"
       },
@@ -21366,9 +22239,9 @@
           }
         },
         "fsevents": {
-          "version": "1.2.11",
-          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
-          "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+          "version": "1.2.12",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz",
+          "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -21422,7 +22295,7 @@
               }
             },
             "chownr": {
-              "version": "1.1.3",
+              "version": "1.1.4",
               "bundled": true,
               "dev": true,
               "optional": true
@@ -21594,7 +22467,7 @@
               }
             },
             "minimist": {
-              "version": "0.0.8",
+              "version": "1.2.5",
               "bundled": true,
               "dev": true,
               "optional": true
@@ -21619,12 +22492,12 @@
               }
             },
             "mkdirp": {
-              "version": "0.5.1",
+              "version": "0.5.3",
               "bundled": true,
               "dev": true,
               "optional": true,
               "requires": {
-                "minimist": "0.0.8"
+                "minimist": "^1.2.5"
               }
             },
             "ms": {
@@ -21634,7 +22507,7 @@
               "optional": true
             },
             "needle": {
-              "version": "2.4.0",
+              "version": "2.3.3",
               "bundled": true,
               "dev": true,
               "optional": true,
@@ -21663,7 +22536,7 @@
               }
             },
             "nopt": {
-              "version": "4.0.1",
+              "version": "4.0.3",
               "bundled": true,
               "dev": true,
               "optional": true,
@@ -21688,13 +22561,14 @@
               "optional": true
             },
             "npm-packlist": {
-              "version": "1.4.7",
+              "version": "1.4.8",
               "bundled": true,
               "dev": true,
               "optional": true,
               "requires": {
                 "ignore-walk": "^3.0.1",
-                "npm-bundled": "^1.0.1"
+                "npm-bundled": "^1.0.1",
+                "npm-normalize-package-bin": "^1.0.1"
               }
             },
             "npmlog": {
@@ -21774,18 +22648,10 @@
                 "ini": "~1.3.0",
                 "minimist": "^1.2.0",
                 "strip-json-comments": "~2.0.1"
-              },
-              "dependencies": {
-                "minimist": {
-                  "version": "1.2.0",
-                  "bundled": true,
-                  "dev": true,
-                  "optional": true
-                }
               }
             },
             "readable-stream": {
-              "version": "2.3.6",
+              "version": "2.3.7",
               "bundled": true,
               "dev": true,
               "optional": true,
@@ -22063,16 +22929,16 @@
       "dev": true
     },
     "webpack": {
-      "version": "4.41.6",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.6.tgz",
-      "integrity": "sha512-yxXfV0Zv9WMGRD+QexkZzmGIh54bsvEs+9aRWxnN8erLWEOehAKUTeNBoUbA6HPEZPlRo7KDi2ZcNveoZgK9MA==",
+      "version": "4.43.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz",
+      "integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==",
       "dev": true,
       "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-module-context": "1.8.5",
-        "@webassemblyjs/wasm-edit": "1.8.5",
-        "@webassemblyjs/wasm-parser": "1.8.5",
-        "acorn": "^6.2.1",
+        "@webassemblyjs/ast": "1.9.0",
+        "@webassemblyjs/helper-module-context": "1.9.0",
+        "@webassemblyjs/wasm-edit": "1.9.0",
+        "@webassemblyjs/wasm-parser": "1.9.0",
+        "acorn": "^6.4.1",
         "ajv": "^6.10.2",
         "ajv-keywords": "^3.4.1",
         "chrome-trace-event": "^1.0.2",
@@ -22083,13 +22949,13 @@
         "loader-utils": "^1.2.3",
         "memory-fs": "^0.4.1",
         "micromatch": "^3.1.10",
-        "mkdirp": "^0.5.1",
+        "mkdirp": "^0.5.3",
         "neo-async": "^2.6.1",
         "node-libs-browser": "^2.2.1",
         "schema-utils": "^1.0.0",
         "tapable": "^1.1.3",
         "terser-webpack-plugin": "^1.4.3",
-        "watchpack": "^1.6.0",
+        "watchpack": "^1.6.1",
         "webpack-sources": "^1.4.1"
       },
       "dependencies": {
@@ -22123,9 +22989,9 @@
           }
         },
         "cacache": {
-          "version": "12.0.3",
-          "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz",
-          "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
+          "version": "12.0.4",
+          "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+          "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
           "dev": true,
           "requires": {
             "bluebird": "^3.5.5",
@@ -22229,14 +23095,15 @@
             "regex-not": "^1.0.0",
             "snapdragon": "^0.8.1",
             "to-regex": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "6.0.3",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-              "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-              "dev": true
-            }
+          }
+        },
+        "mkdirp": {
+          "version": "0.5.5",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+          "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.5"
           }
         },
         "schema-utils": {
@@ -22295,13 +23162,13 @@
       }
     },
     "webpack-bundle-analyzer": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.6.0.tgz",
-      "integrity": "sha512-orUfvVYEfBMDXgEKAKVvab5iQ2wXneIEorGNsyuOyVYpjYrI7CUOhhXNDd3huMwQ3vNNWWlGP+hzflMFYNzi2g==",
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.7.0.tgz",
+      "integrity": "sha512-mETdjZ30a3Yf+NTB/wqTgACK7rAYQl5uxKK0WVTNmF0sM3Uv8s3R58YZMW7Rhu0Lk2Rmuhdj5dcH5Q76zCDVdA==",
       "dev": true,
       "requires": {
-        "acorn": "^6.0.7",
-        "acorn-walk": "^6.1.1",
+        "acorn": "^7.1.1",
+        "acorn-walk": "^7.1.1",
         "bfj": "^6.1.1",
         "chalk": "^2.4.1",
         "commander": "^2.18.0",
@@ -22315,6 +23182,18 @@
         "ws": "^6.0.0"
       },
       "dependencies": {
+        "acorn": {
+          "version": "7.1.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
+          "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
+          "dev": true
+        },
+        "acorn-walk": {
+          "version": "7.1.1",
+          "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz",
+          "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==",
+          "dev": true
+        },
         "chalk": {
           "version": "2.4.2",
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -22362,9 +23241,9 @@
           }
         },
         "mime": {
-          "version": "2.4.4",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
-          "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+          "version": "2.4.5",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz",
+          "integrity": "sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==",
           "dev": true
         }
       }
@@ -22547,9 +23426,9 @@
           }
         },
         "fsevents": {
-          "version": "1.2.11",
-          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
-          "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+          "version": "1.2.12",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz",
+          "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -22603,7 +23482,7 @@
               }
             },
             "chownr": {
-              "version": "1.1.3",
+              "version": "1.1.4",
               "bundled": true,
               "dev": true,
               "optional": true
@@ -22775,7 +23654,7 @@
               }
             },
             "minimist": {
-              "version": "0.0.8",
+              "version": "1.2.5",
               "bundled": true,
               "dev": true,
               "optional": true
@@ -22800,12 +23679,12 @@
               }
             },
             "mkdirp": {
-              "version": "0.5.1",
+              "version": "0.5.3",
               "bundled": true,
               "dev": true,
               "optional": true,
               "requires": {
-                "minimist": "0.0.8"
+                "minimist": "^1.2.5"
               }
             },
             "ms": {
@@ -22815,7 +23694,7 @@
               "optional": true
             },
             "needle": {
-              "version": "2.4.0",
+              "version": "2.3.3",
               "bundled": true,
               "dev": true,
               "optional": true,
@@ -22844,7 +23723,7 @@
               }
             },
             "nopt": {
-              "version": "4.0.1",
+              "version": "4.0.3",
               "bundled": true,
               "dev": true,
               "optional": true,
@@ -22869,13 +23748,14 @@
               "optional": true
             },
             "npm-packlist": {
-              "version": "1.4.7",
+              "version": "1.4.8",
               "bundled": true,
               "dev": true,
               "optional": true,
               "requires": {
                 "ignore-walk": "^3.0.1",
-                "npm-bundled": "^1.0.1"
+                "npm-bundled": "^1.0.1",
+                "npm-normalize-package-bin": "^1.0.1"
               }
             },
             "npmlog": {
@@ -22955,18 +23835,10 @@
                 "ini": "~1.3.0",
                 "minimist": "^1.2.0",
                 "strip-json-comments": "~2.0.1"
-              },
-              "dependencies": {
-                "minimist": {
-                  "version": "1.2.0",
-                  "bundled": true,
-                  "dev": true,
-                  "optional": true
-                }
               }
             },
             "readable-stream": {
-              "version": "2.3.6",
+              "version": "2.3.7",
               "bundled": true,
               "dev": true,
               "optional": true,
@@ -23679,6 +24551,15 @@
         "errno": "~0.1.7"
       }
     },
+    "worker-rpc": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz",
+      "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==",
+      "dev": true,
+      "requires": {
+        "microevent.ts": "~0.1.1"
+      }
+    },
     "wrap-ansi": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
@@ -23743,6 +24624,34 @@
         "signal-exit": "^3.0.2"
       }
     },
+    "write-file-webpack-plugin": {
+      "version": "4.5.1",
+      "resolved": "https://registry.npmjs.org/write-file-webpack-plugin/-/write-file-webpack-plugin-4.5.1.tgz",
+      "integrity": "sha512-AZ7qJUvhTCBiOtG21aFJUcNuLVo2FFM6JMGKvaUGAH+QDqQAp2iG0nq3GcuXmJOFQR2JjpjhyYkyPrbFKhdjNQ==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.4.0",
+        "debug": "^3.1.0",
+        "filesize": "^3.6.1",
+        "lodash": "^4.17.13",
+        "mkdirp": "^0.5.1",
+        "moment": "^2.22.1",
+        "write-file-atomic": "^2.3.0"
+      },
+      "dependencies": {
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        }
+      }
+    },
     "ws": {
       "version": "6.2.1",
       "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
@@ -23813,9 +24722,9 @@
       "dev": true
     },
     "yargs": {
-      "version": "15.1.0",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.1.0.tgz",
-      "integrity": "sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==",
+      "version": "15.3.1",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
+      "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
       "requires": {
         "cliui": "^6.0.0",
         "decamelize": "^1.2.0",
@@ -23827,9 +24736,41 @@
         "string-width": "^4.2.0",
         "which-module": "^2.0.0",
         "y18n": "^4.0.0",
-        "yargs-parser": "^16.1.0"
+        "yargs-parser": "^18.1.1"
       },
       "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "cliui": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+          "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+          "requires": {
+            "string-width": "^4.2.0",
+            "strip-ansi": "^6.0.0",
+            "wrap-ansi": "^6.2.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+        },
         "find-up": {
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@@ -23884,6 +24825,25 @@
             "is-fullwidth-code-point": "^3.0.0",
             "strip-ansi": "^6.0.0"
           }
+        },
+        "wrap-ansi": {
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
+          }
+        },
+        "yargs-parser": {
+          "version": "18.1.2",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.2.tgz",
+          "integrity": "sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ==",
+          "requires": {
+            "camelcase": "^5.0.0",
+            "decamelize": "^1.2.0"
+          }
         }
       }
     },
@@ -23891,6 +24851,7 @@
       "version": "16.1.0",
       "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz",
       "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==",
+      "dev": true,
       "requires": {
         "camelcase": "^5.0.0",
         "decamelize": "^1.2.0"
@@ -23905,6 +24866,30 @@
         "buffer-crc32": "~0.2.3",
         "fd-slicer": "~1.1.0"
       }
+    },
+    "zip-stream": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-3.0.1.tgz",
+      "integrity": "sha512-r+JdDipt93ttDjsOVPU5zaq5bAyY+3H19bDrThkvuVxC0xMQzU1PJcS6D+KrP3u96gH9XLomcHPb+2skoDjulQ==",
+      "dev": true,
+      "requires": {
+        "archiver-utils": "^2.1.0",
+        "compress-commons": "^3.0.0",
+        "readable-stream": "^3.6.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
     }
   }
 }
diff --git a/package.json b/package.json
index 74c69a22..2b4a4898 100644
--- a/package.json
+++ b/package.json
@@ -31,40 +31,40 @@
     "apidoc": "jsdoc2md src-electron/**/*.js > docs/api.md"
   },
   "dependencies": {
-    "@quasar/extras": "^1.5.2",
+    "@quasar/extras": "^1.7.0",
     "axios": "^0.18.1",
     "body-parser": "^1.19.0",
     "crc": "^3.8.0",
     "electron-builder": "^20.44.4",
     "express": "^4.17.1",
-    "express-session": "^1.17.0",
-    "node-abi": "^2.15.0",
+    "express-session": "^1.17.1",
+    "node-abi": "^2.16.0",
     "node-gyp": "^6.1.0",
     "node-pre-gyp": "^0.14.0",
-    "pino": "^5.16.0",
+    "pino": "^5.17.0",
     "properties": "^1.2.1",
-    "quasar": "^1.9.3",
-    "sqlite3": "^4.1.1",
+    "quasar": "^1.10.5",
+    "sqlite3": "^4.2.0",
     "xml2js": "^0.4.23",
-    "yargs": "^15.1.0"
+    "yargs": "^15.3.1"
   },
   "devDependencies": {
-    "@quasar/app": "^1.5.8",
+    "@quasar/app": "^1.8.4",
     "@quasar/quasar-app-extension-testing": "^1.0.0",
     "@quasar/quasar-app-extension-testing-unit-jest": "^1.0.0",
     "@vue/eslint-config-standard": "^4.0.0",
-    "babel-eslint": "^10.0.1",
+    "babel-eslint": "^10.1.0",
     "devtron": "^1.4.0",
-    "electron": "^8.2.0",
+    "electron": "^8.2.5",
     "electron-debug": "^3.0.1",
     "electron-devtools-installer": "^2.2.4",
     "electron-packager": "^14.2.1",
-    "electron-rebuild": "^1.10.0",
+    "electron-rebuild": "^1.10.1",
     "eslint": "^5.10.0",
     "eslint-loader": "^2.1.1",
     "eslint-plugin-vue": "^5.0.0",
     "file-loader": "^5.1.0",
-    "jsdoc": "^3.6.3",
+    "jsdoc": "^3.6.4",
     "jsdoc-to-markdown": "^5.0.3",
     "license-checker": "^25.0.1"
   },
diff --git a/quasar.conf.js b/quasar.conf.js
index d7aad8a9..977b5a20 100644
--- a/quasar.conf.js
+++ b/quasar.conf.js
@@ -19,7 +19,7 @@ module.exports = function (ctx) {
     // app boot file (/src/boot)
     // --> boot files are part of "main.js"
     // https://quasar.dev/quasar-cli/cli-documentation/boot-files
-    boot: ['axios'],
+    boot: ['axios', 'globalapi'],
 
     // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css
     css: [
@@ -183,7 +183,8 @@ module.exports = function (ctx) {
         // win32metadata: { ... }
 
         platform: 'darwin,linux,win32',
-        arch: 'ia32,x64',
+        //arch: 'ia32,x64',
+        arch: 'x64',
         extraResource: 'src-electron/db/zap-schema.sql',
         afterCopy: [(buildPath, electronVersion, platform, arch, callback) => {
           require('electron-rebuild').rebuild({ buildPath, electronVersion, arch })
diff --git a/src-electron/db/db-api.js b/src-electron/db/db-api.js
index 8fbcb944..4053edc7 100644
--- a/src-electron/db/db-api.js
+++ b/src-electron/db/db-api.js
@@ -107,14 +107,16 @@ export function dbUpdate(db, query, args) {
  * @param {*} args
  * @returns A promise that resolves with the rowid from the inserted row, or rejects with an error from the query.
  */
-export function dbInsert(db, query, args) {
+export function dbInsert(db, query, args, enabledLogging = true) {
     return new Promise((resolve, reject) => {
         db.run(query, args, function (err) {
             if (err) {
-                logError(`Failed insert: ${query}: ${args}`)
+                if ( enabledLogging)
+                    logError(`Failed insert: ${query}: ${args}`)
                 reject(err)
             } else {
-                logInfo(`Executed insert: ${query}: ${args} => rowid: ${this.lastID}`)
+                if ( enabledLogging)
+                    logInfo(`Executed insert: ${query}: ${args} => rowid: ${this.lastID}`)
                 resolve(this.lastID)
             }
         })
diff --git a/src-electron/db/query-config.js b/src-electron/db/query-config.js
new file mode 100644
index 00000000..cc5f8cf5
--- /dev/null
+++ b/src-electron/db/query-config.js
@@ -0,0 +1,485 @@
+// Copyright (c) 2020 Silicon Labs. All rights reserved.
+
+/** 
+ * This module provides queries for user configuration.
+ * 
+ * @module DB API: user configuration queries against the database.
+ */
+import { dbAll, dbGet, dbInsert, dbMultiInsert, dbRemove, dbUpdate, dbBeginTransaction, dbCommit } from './db-api.js'
+import { selectAttributeByAttributeRef } from './query-zcl.js'
+import { zclDeviceTypeClusters, zclDeviceTypeAttributes, zclDeviceTypeCommands, zclAttributes, zclCommands } from '../zcl/zcl-model.js'
+import { logError, logInfo } from '../main-process/env.js'
+
+
+
+
+/**
+ * Promises to update or insert a key/value pair in SESSION_KEY_VALUE table.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @param {*} key
+ * @param {*} value
+ * @returns A promise of creating or updating a row, resolves with the rowid of a new row.
+ */
+export function updateKeyValue(db, sessionId, key, value) {
+    return dbInsert(db, "INSERT OR REPLACE INTO SESSION_KEY_VALUE (SESSION_REF, KEY, VALUE) VALUES (?,?,?)", [sessionId, key, value])
+}
+/**
+ * Promises to update the cluster include/exclude state.
+ * If the entry [as defined uniquely by endpointTypeId, clusterId, side] is not there, then insert
+ * Else update the entry in place. 
+ * 
+ * @export
+ * @param {*} db
+ * @param {*} endpointTypeId
+ * @param {*} clusterRef
+ * @param {*} side 
+ * @param {*} enabled
+ * @returns Promise to update the cluster exclude/include state.
+ */
+export function insertOrReplaceClusterState(db, endpointTypeId, clusterRef, side, enabled) {
+    return dbGet(db, "SELECT COUNT(1) FROM ENDPOINT_TYPE_CLUSTER WHERE ENDPOINT_TYPE_REF = ? AND CLUSTER_REF = ? AND SIDE = ?", [endpointTypeId, clusterRef, side])
+        .then(count => {
+            if (count['COUNT(1)'] > 0) {
+                return dbUpdate(db, "UPDATE ENDPOINT_TYPE_CLUSTER SET ENABLED = ? WHERE ENDPOINT_TYPE_REF = ? AND CLUSTER_REF = ? AND SIDE = ?", [enabled, endpointTypeId, clusterRef, side])
+            } else {
+                return dbInsert(db, "INSERT OR REPLACE INTO ENDPOINT_TYPE_CLUSTER ( ENDPOINT_TYPE_REF, CLUSTER_REF, SIDE, ENABLED ) VALUES ( ?, ?, ?, ?)", [endpointTypeId, clusterRef, side, enabled])
+            }
+        })
+}
+
+/**
+ * Promise to update the attribute state. 
+ * If the attribute entry [as defined uniquely by endpointTypeId and id], is not there, then create a default entry
+ * Afterwards, update entry. 
+ * @param {*} db 
+ * @param {*} endpointTypeId 
+ * @param {*} id 
+ * @param {*} value
+ * @param {*} booleanParam 
+ */
+export function insertOrUpdateAttributeState(db, endpointTypeId, id, value, param) {
+    return selectAttributeByAttributeRef(db, id).then(staticAttribute => {
+        return dbGet(db, "SELECT COUNT(1) FROM ENDPOINT_TYPE_ATTRIBUTE WHERE ENDPOINT_TYPE_REF = ? AND ATTRIBUTE_REF = ?", [endpointTypeId, id])
+            .then(count => {
+                return ((count['COUNT(1)'] == 0 ?
+                    dbInsert(db, "INSERT INTO ENDPOINT_TYPE_ATTRIBUTE (ENDPOINT_TYPE_REF, ATTRIBUTE_REF, INCLUDED, EXTERNAL, FLASH, SINGLETON, BOUNDED, DEFAULT_VALUE) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?)", [endpointTypeId, id, false, false, false, false, false, staticAttribute.DEFAULT_VALUE ? staticAttribute.DEFAULT_VALUE : ""])
+                    : new Promise((resolve, reject) => {
+                        resolve()
+                    })).then(promiseResult => dbUpdate(db, "UPDATE ENDPOINT_TYPE_ATTRIBUTE SET " + param + " = ? WHERE ENDPOINT_TYPE_REF = ? AND ATTRIBUTE_REF = ?", [value, endpointTypeId, id])))
+            })
+    })
+}
+
+/**
+ * Promise to update the command state. 
+ * If the attribute entry [as defined uniquely by endpointTypeId and id], is not there, then create a default entry
+ * Afterwards, update entry. 
+ * @param {*} db 
+ * @param {*} endpointTypeId 
+ * @param {*} id 
+ * @param {*} value
+ * @param {*} booleanParam 
+ */
+export function insertOrUpdateCommandState(db, endpointTypeId, id, value, param) {
+    return dbGet(db, "SELECT COUNT(1) FROM ENDPOINT_TYPE_COMMAND WHERE ENDPOINT_TYPE_REF = ? AND COMMAND_REF = ?", [endpointTypeId, id])
+        .then(count => {
+            return ((count['COUNT(1)'] == 0 ?
+                dbInsert(db, "INSERT INTO ENDPOINT_TYPE_COMMAND (ENDPOINT_TYPE_REF, COMMAND_REF, INCOMING, OUTGOING) VALUES ( ?, ?, ?, ?)", [endpointTypeId, id, false, false])
+                : new Promise((resolve, reject) => {
+                    resolve()
+                })).then(promiseResult => dbUpdate(db, "UPDATE ENDPOINT_TYPE_COMMAND SET " + param + " = ? WHERE ENDPOINT_TYPE_REF = ? AND COMMAND_REF = ?", [value, endpointTypeId, id])))
+        })
+}
+
+/**
+ * Promise to update the reportable attribute state. 
+ * If the reportable attribute entry [as defined uniquely by endpointTypeId and id], is not there, then create a default entry
+ * Afterwards, update entry. 
+ * @param {*} db 
+ * @param {*} endpointTypeId 
+ * @param {*} id 
+ * @param {*} value
+ * @param {*} booleanParam 
+ */
+export function insertOrUpdateReportableAttributeState(db, endpointTypeId, id, value, param) {
+    return dbGet(db, "SELECT COUNT(1) FROM ENDPOINT_TYPE_REPORTABLE_ATTRIBUTE WHERE ENDPOINT_TYPE_REF = ? AND ATTRIBUTE_REF = ?", [endpointTypeId, id])
+        .then(count => {
+            return ((count['COUNT(1)'] == 0 ?
+                dbInsert(db, "INSERT INTO ENDPOINT_TYPE_REPORTABLE_ATTRIBUTE (ENDPOINT_TYPE_REF, ATTRIBUTE_REF, INCLUDED, MIN_INTERVAL, MAX_INTERVAL, REPORTABLE_CHANGE) VALUES ( ?, ?, ?, ?, ?, ?)", [endpointTypeId, id, false, 0, 65344, 0])
+                : new Promise((resolve, reject) => {
+                    resolve()
+                })).then(promiseResult => dbUpdate(db, "UPDATE ENDPOINT_TYPE_REPORTABLE_ATTRIBUTE SET " + param + " = ? WHERE ENDPOINT_TYPE_REF = ? AND ATTRIBUTE_REF = ?", [value, endpointTypeId, id])))
+        })
+}
+
+/*
+  Resolves into all the cluster states.
+*/
+export function getAllEndpointTypeClusterState(db, endpointTypeId) {
+    return dbAll(db, "SELECT CLUSTER.NAME, CLUSTER.CODE, CLUSTER.MANUFACTURER_CODE, ENDPOINT_TYPE_CLUSTER.SIDE, ENDPOINT_TYPE_CLUSTER.ENABLED FROM ENDPOINT_TYPE_CLUSTER INNER JOIN CLUSTER WHERE ENDPOINT_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID AND ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF = ?", [endpointTypeId])
+        .then((rows) => new Promise((resolve, reject) => {
+            if (rows == null) {
+                resolve([])
+            } else {
+                var result = rows.map(row => {
+                    var obj = {
+                        clusterName: row.NAME,
+                        clusterCode: row.CODE,
+                        side: row.SIDE,
+                        enabled: (row.STATE == '1')
+                    }
+                    if (row.MANUFACTURER_CODE != null)
+                        obj.manufacturerCode = row.MANUFACTURER_CODE;
+                    return obj
+                })
+                resolve(result)
+            }
+        }))
+}
+
+/**
+* Promises to add an endpoint. 
+*
+* @export
+* @param {*} db
+* @param {*} sessionId
+* @param {*} endpointId
+* @param {*} endpointTypeRef
+* @param {*} networkId
+* @returns Promise to update endpoints. 
+*/
+export function insertEndpoint(db, sessionId, endpointId, endpointTypeRef, networkId) {
+    return dbInsert(db, "INSERT OR REPLACE INTO ENDPOINT ( SESSION_REF, ENDPOINT_ID, ENDPOINT_TYPE_REF, NETWORK_ID ) VALUES ( ?, ?, ?, ?)", [sessionId, endpointId, endpointTypeRef, networkId])
+}
+
+/**
+ * Deletes an endpoint.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} id
+ * @returns Promise to delete an endpoint that resolves with the number of rows that were deleted.
+ */
+export function deleteEndpoint(db, id) {
+    return dbRemove(db, "DELETE FROM ENDPOINT WHERE ENDPOINT_REF = ?", [id])
+}
+
+export function editEndpoint(db, sessionId, endpointRef, param, updatedValue) {
+    return dbUpdate(db, "UPDATE ENDPOINT SET " + param + " = ? WHERE ENDPOINT_REF = ? AND SESSION_REF = ?", [updatedValue, endpointRef, sessionId])
+}
+
+/**
+* Promises to add an endpoint type. 
+*
+* @export
+* @param {*} db
+* @param {*} sessionId
+* @param {*} name
+* @param {*} deviceTypeRef
+* @returns Promise to update endpoints. 
+*/
+export function insertEndpointType(db, sessionId, name, deviceTypeRef) {
+    return dbInsert(db, "INSERT OR REPLACE INTO ENDPOINT_TYPE ( SESSION_REF, NAME, DEVICE_TYPE_REF ) VALUES ( ?, ?, ?)", [sessionId, name, deviceTypeRef]).then(newEndpointId => {
+        return setEndpointDefaults(db, newEndpointId, deviceTypeRef).then(newData => {
+            return newEndpointId
+        })
+    })
+}
+
+/**
+ * Promise to delete an endpoint type. 
+ * @param {*} db 
+ * @param {*} sessionId 
+ * @param {*} id 
+ */
+
+export function deleteEndpointType(db, id) {
+    return dbRemove(db, "DELETE FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = ?", [id])
+}
+
+
+export function deleteEndpointTypeData(db, endpointTypeId) {
+    return Promise.all([dbRemove(db, "DELETE FROM ENDPOINT_TYPE_CLUSTER WHERE ENDPOINT_TYPE_REF = ?", [endpointTypeId]),
+                        dbRemove(db, "DELETE FROM ENDPOINT_TYPE_ATTRIBUTE WHERE ENDPOINT_TYPE_REF = ?", [endpointTypeId]),
+                        dbRemove(db, "DELETE FROM ENDPOINT_TYPE_COMMAND WHERE ENDPOINT_TYPE_REF = ?", [endpointTypeId]),
+                        dbRemove(db, "DELETE FROM ENDPOINT_TYPE_REPORTABLE_ATTRIBUTE WHERE ENDPOINT_TYPE_REF = ? ", [endpointTypeId])])
+}
+
+/**
+ * Promise to update a an endpoint type. 
+ * @param {*} db 
+ * @param {*} sessionId 
+ * @param {*} endpointTypeId 
+ * @param {*} param 
+ * @param {*} updatedValue 
+ */
+export function updateEndpointType(db, sessionId, endpointTypeId, param, updatedValue) {
+    return dbUpdate(db, "UPDATE ENDPOINT_TYPE SET " + param + " = ? WHERE ENDPOINT_TYPE_ID = ? AND SESSION_REF = ?", [updatedValue, endpointTypeId, sessionId]).then(newEndpointId => {
+        if (param === 'DEVICE_TYPE_REF') {
+            return new Promise((resolve, reject) => deleteEndpointTypeData(db, endpointTypeId)
+                .then(newData => setEndpointDefaults(db, endpointTypeId, updatedValue).then(newData => {
+                    resolve(newEndpointId)
+                })))
+        } else {
+            return new Promise((resolve, reject) => resolve(newEndpointId))
+        }
+    })
+}
+
+
+/**
+ * Promise to set the default attributes and clusters for a endpoint type. 
+ * @param {*} db 
+ * @param {*} endpointTypeId 
+ */
+export function setEndpointDefaults(db, endpointTypeId, deviceTypeRef) {
+    var promises = []
+    return dbBeginTransaction(db)
+        .then(data => {
+            var clusterPromise = resolveDefaultClusters(db, endpointTypeId, deviceTypeRef)
+            promises.push(resolveDefaultDeviceTypeAttributes(db, endpointTypeId, deviceTypeRef))
+            promises.push(resolveDefaultDeviceTypeCommands(db, endpointTypeId, deviceTypeRef))
+            promises.push(clusterPromise.then(data => {
+                var clusters = data.flat()
+                var dataPromises = new Promise((resolve, reject) => {
+                    promises.push(resolveDefaultAttributes(db, endpointTypeId, clusters))
+                    promises.push(resolveNonOptionalCommands(db, endpointTypeId, clusters))
+                    resolve()
+                })
+                return Promise.all([dataPromises])
+            }))
+            return Promise.all(promises)
+        }).then(data => {
+            return dbCommit(db)
+        }).catch(err => {
+            console.log(err)
+        })
+}
+
+function resolveDefaultClusters(db, endpointTypeId, deviceTypeRef) {
+    return zclDeviceTypeClusters(db, deviceTypeRef).then(clusters => {
+        return Promise.all(clusters.map(cluster => {
+            var clientServerPromise = []
+            if (cluster.includeClient) {
+                clientServerPromise.push(
+                    new Promise((resolve, reject) =>
+                        insertOrReplaceClusterState(db, endpointTypeId, cluster.clusterRef, 'client', true).then(data => {
+                            resolve({ clusterRef: cluster.clusterRef, side: 'client' })
+                        })))
+            }
+            if (cluster.includeServer) {
+                clientServerPromise.push(
+                    new Promise((resolve, reject) =>
+                        insertOrReplaceClusterState(db, endpointTypeId, cluster.clusterRef, 'server', true).then(data => {
+                            resolve({ clusterRef: cluster.clusterRef, side: 'server' })
+                        })))
+            }
+            return Promise.all(clientServerPromise)
+        }))
+    })
+}
+
+
+function resolveDefaultDeviceTypeAttributes(db, endpointTypeId, deviceTypeRef) {
+    return zclDeviceTypeAttributes(db, deviceTypeRef).then(attributes => {
+        return Promise.all(attributes.map(attribute => {
+            if (attribute.attributeRef != null) {
+                return Promise.all([insertOrUpdateAttributeState(db, endpointTypeId, attribute.attributeRef, true, 'INCLUDED'),
+                                    resolveReportableAttribute(db, endpointTypeId, attribute)
+                                    ])
+            } else {
+                return new Promise((resolve, reject) => {
+                    return resolve();
+                })
+            }
+        }))
+    })
+}
+
+function resolveReportableAttribute(db, endpointTypeId, attribute) {
+    if (attribute.isReportable) {
+        return insertOrUpdateReportableAttributeState(db, endpointTypeId, attribute.id, true, "INCLUDED")
+    } else {
+        return new Promise((resolve, reject) => {
+            return resolve();
+        })
+    }
+}
+
+
+function resolveReportableAttributesList(db, endpointTypeId, attributes) {
+    return Promise.all(attributes.map(attribute => {
+        return resolveReportableAttribute(db, endpointTypeId, attribute)
+    }))
+}
+
+function resolveDefaultDeviceTypeCommands(db, endpointTypeId, deviceTypeRef) {
+    return zclDeviceTypeCommands(db, deviceTypeRef).then(commands => {
+        return Promise.all(commands.map(command => {
+            if (command.commandRef != null) {
+                return insertOrUpdateCommandState(db, endpointTypeId, command.commandRef, true, 'OUTGOING')
+            } else {
+                return new Promise((resolve, reject) => {
+                    return resolve();
+                })
+            }
+        }))
+    })
+}
+
+function resolveNonOptionalCommands(db, endpointTypeId, clusters) {
+    return Promise.all(clusters.map(cluster => {
+        return zclCommands(db, cluster.clusterRef).then(commands => {
+            return Promise.all(commands.map(command => {
+                if (!command.isOptional) {
+                    return insertOrUpdateCommandState(db, endpointTypeId, command.id, true, 'OUTGOING')
+                } else {
+                    return new Promise((resolve, reject) => {
+                        return resolve();
+                    })
+                }
+            }))
+        })
+    }))
+}
+
+function resolveDefaultAttributes(db, endpointTypeId, clusters) {
+    return Promise.all(clusters.map(cluster => {
+        return zclAttributes(db, cluster.clusterRef).then(attributes => {
+            var promiseArray = []
+            promiseArray.push(resolveReportableAttributesList(db, endpointTypeId, attributes))
+            promiseArray.push(resolveNonOptionalAttributes(db, endpointTypeId, attributes))
+            return Promise.all(promiseArray)
+        })
+    }))
+}
+
+function resolveNonOptionalAttributes(db, endpointTypeId, attributes) {
+    return Promise.all(attributes.map(attribute => {
+        if (!attribute.isOptional) {
+            return insertOrUpdateAttributeState(db, endpointTypeId, attribute.id, true, "INCLUDED")
+        } else {
+            return new Promise((resolve, reject) => {
+                return resolve();
+            })
+        }
+    }))
+}
+
+
+
+/**
+ * Resolves to an array of objects that contain 'key' and 'value'
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @returns Promise to retrieve all session key values.
+ */
+export function getAllSesionKeyValues(db, sessionId) {
+    return dbAll(db, "SELECT KEY, VALUE FROM SESSION_KEY_VALUE WHERE SESSION_REF = ? ORDER BY KEY", [sessionId])
+        .then((rows) => new Promise((resolve, reject) => {
+            if (rows == null) {
+                resolve([])
+            } else {
+                var result = rows.map(row => {
+                    return {
+                        key: row.KEY,
+                        value: row.VALUE
+                    }
+                })
+                resolve(result)
+            }
+        }))
+}
+/**
+ * Resolves to an array of endpoint types.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @returns Promise to retrieve all endpoint types.
+ */
+export function getAllEndpointTypes(db, sessionId) {
+    return dbAll(db, "SELECT ENDPOINT_TYPE_ID, NAME, DEVICE_TYPE_REF FROM ENDPOINT_TYPE WHERE SESSION_REF = ? ORDER BY NAME", [sessionId])
+        .then((rows) => new Promise((resolve, reject) => {
+            if (rows == null) {
+                resolve([])
+            } else {
+                var result = rows.map(row => {
+                    return {
+                        endpointTypeId: row.ENDPOINT_TYPE_ID,
+                        name: row.NAME,
+                        deviceTypeId: row.DEVICE_TYPE_REF
+                    }
+                })
+                resolve(result)
+            }
+        }))
+        .then(result => {
+            var promises = []
+            result.forEach(row => {
+                promises.push(new Promise((resolve, reject) => {
+                    return dbAll(db, "SELECT CLUSTER_REF, SIDE, ENABLED FROM ENDPOINT_TYPE_CLUSTER WHERE ENDPOINT_TYPE_REF = ?", [row.endpointTypeId])
+                        .then(rows => new Promise((resolve, reject) => {
+                            if (rows != null)
+                                row.clusters = rows
+                            resolve()
+                        })).then(() => resolve())
+                        .catch(err => {
+                            logError(err)
+                            throw err
+                        })
+                }))
+
+                promises.push(new Promise((resolve, reject) => {
+                    return dbAll(db, "SELECT ATTRIBUTE_REF, INCLUDED, EXTERNAL, FLASH, SINGLETON, BOUNDED, DEFAULT_VALUE FROM ENDPOINT_TYPE_ATTRIBUTE WHERE ENDPOINT_TYPE_REF = ?", [row.endpointTypeId])
+                        .then(rows => new Promise((resolve, reject) => {
+                            if (rows != null)
+                                row.attributes = rows
+                            resolve()
+                        })).then(() => resolve())
+                        .catch(err => {
+                            logError(err)
+                            throw err
+                        })
+                }))
+
+                promises.push(new Promise((resolve, reject) => {
+                    return dbAll(db, "SELECT COMMAND_REF, INCOMING, OUTGOING FROM ENDPOINT_TYPE_COMMAND WHERE ENDPOINT_TYPE_REF = ?", [row.endpointTypeId])
+                        .then(rows => new Promise((resolve, reject) => {
+                            if (rows != null)
+                                row.commands = rows
+                            resolve()
+                        })).then(() => resolve())
+                        .catch(err => {
+                            logError(err)
+                            throw err
+                        })
+                }))
+            })
+            return Promise.all(promises).then(() => Promise.resolve(result))
+        })
+}
+
+export function getAllEndpoints(db, sessionId) {
+    return dbAll(db, "SELECT ENDPOINT_TYPE_REF, PROFILE, NETWORK_ID WHERE SESSION_REF = ?", [sessionId])
+        .then((rows) => new Promise((resolve, reject) => {
+            if (rows == null) {
+                resolve([])
+            } else {
+                var result = rows.map(row => {
+                    return {
+                        profile: row.PROFILE,
+                        networkId: row.NETWORK_ID,
+                        endpointType: row.ENDPOINT_TYPE_REF
+                    }
+                })
+                resolve(result)
+            }
+        }))
+}
+
diff --git a/src-electron/db/query-generic.js b/src-electron/db/query-generic.js
new file mode 100644
index 00000000..cad3a65e
--- /dev/null
+++ b/src-electron/db/query-generic.js
@@ -0,0 +1,50 @@
+// Copyright (c) 2020 Silicon Labs. All rights reserved.
+
+/** 
+ * This module provides generic queries.
+ * 
+ * @module DB API: generic queries against the database.
+ */
+import { dbGet, dbInsert } from './db-api.js'
+
+/**
+ * Simple query that returns number of rows in a given table.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} table
+ * @returns a promise that resolves into the count of the rows in the table.
+ */
+export function selectCountFrom(db, table) {
+    return dbGet(db, `SELECT COUNT(*) FROM ${table}`).then(x => x['COUNT(*)'])
+}
+
+/**
+ * Writes the saved location of the file.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} filePath
+ * @param {*} category
+ */
+export function insertFileLocation(db, filePath, category) {
+    return dbInsert(db, 'INSERT OR REPLACE INTO FILE_LOCATION (CATEGORY, FILE_PATH, ACCESS_TIME) VALUES (?,?,?)', [category, filePath, Date.now()])
+}
+
+/**
+ * Retrieves the saved location from a file
+ *
+ * @export
+ * @param {*} db
+ * @param {*} category
+ */
+export function selectFileLocation(db, category) {
+    return dbGet(db, 'SELECT FILE_PATH FROM FILE_LOCATION WHERE CATEGORY = ?', [category])
+        .then(row => {
+            if (row == null) {
+                return Promise.resolve('')
+            } else {
+                return Promise.resolve(row.FILE_PATH)
+            }
+        })
+}
\ No newline at end of file
diff --git a/src-electron/db/query-package.js b/src-electron/db/query-package.js
new file mode 100644
index 00000000..b0ad2b61
--- /dev/null
+++ b/src-electron/db/query-package.js
@@ -0,0 +1,70 @@
+// Copyright (c) 2020 Silicon Labs. All rights reserved.
+
+/** 
+ * This module provides queries related to packages.
+ * 
+ * @module DB API: package-based queries.
+ */
+import { dbGet, dbInsert } from './db-api.js'
+
+/**
+ * Checks if the package with a given path exists and executes appropriate action.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} path Path of a file to check.
+ * @param {*} crcCallback This callback is executed if the row exists, with arguments (CRC, PACKAGE_ID)
+ * @param {*} noneCallback This callback is executed if the row does not exist.
+ */
+export function forPathCrc(db, path, crcCallback, noneCallback) {
+    dbGet(db, "SELECT PACKAGE_ID, PATH, CRC FROM PACKAGE WHERE PATH = ?", [path]).then(row => {
+        if (row == null) {
+            noneCallback()
+        } else {
+            crcCallback(row.CRC, row.PACKAGE_ID)
+        }
+    })
+}
+
+/**
+ * Resolves with a CRC or null for a given path.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} path
+ * @returns Promise resolving with a CRC or null.
+ */
+export function getPathCrc(db, path) {
+    return dbGet(db, "SELECT CRC FROM PACKAGE WHERE PATH = ?", [path]).then(row => new Promise((resolve, reject) => {
+        if (row == null) {
+            resolve(null)
+        } else {
+            resolve(row.CRC)
+        }
+    }))
+}
+
+/**
+ * Inserts a given path CRC combination into the table.
+ * 
+ * @param {*} db 
+ * @param {*} path Path of the file.
+ * @param {*} crc CRC of the file.
+ * @returns Promise of an insertion.
+ */
+export function insertPathCrc(db, path, crc) {
+    return dbInsert(db, "INSERT INTO PACKAGE ( PATH, CRC ) VALUES (?, ?)", [path, crc])
+}
+
+/**
+ * Updates a CRC in the table.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} path
+ * @param {*} crc
+ * @returns Promise of an update.
+ */
+export function updatePathCrc(db, path, crc) {
+    return dbInsert(db, "UPDATE PACKAGE SET CRC = ? WHERE PATH = ?", [path, crc])
+}
diff --git a/src-electron/db/query-session.js b/src-electron/db/query-session.js
new file mode 100644
index 00000000..b9ee8191
--- /dev/null
+++ b/src-electron/db/query-session.js
@@ -0,0 +1,137 @@
+// Copyright (c) 2020 Silicon Labs. All rights reserved.
+
+/** 
+ * This module provides session related queries.
+ * 
+ * @module DB API: session related queries.
+ */
+import { dbAll, dbGet, dbInsert, dbRemove, dbUpdate } from './db-api.js'
+
+/**
+ * Returns a promise that resolves into an array of objects containing 'sessionId', 'sessionKey' and 'creationTime'.
+ *
+ * @export
+ * @param {*} db
+ * @returns A promise of executing a query.
+ */
+export function getAllSessions(db) {
+    return dbAll(db, "SELECT SESSION_ID, SESSION_KEY, CREATION_TIME FROM SESSION", [])
+        .then(rows => {
+            if (rows == null) {
+                reject()
+            } else {
+                var map = rows.map(row => {
+                    return {
+                        sessionId: row.SESSION_ID,
+                        sessionKey: row.SESSION_KEY,
+                        creationTime: row.CREATION_TIME
+                    }
+                })
+                return Promise.resolve(map)
+            }
+        })
+}
+
+/**
+ * Sets the session dirty flag to false.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @returns A promise that resolves with the number of rows updated.
+ */
+export function setSessionClean(db, sessionId) {
+    return dbUpdate(db, "UPDATE SESSION SET DIRTY = ? WHERE SESSION_ID = ?", [0, sessionId])
+}
+/**
+ * Resolves with true or false, depending whether this session is dirty.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @returns A promise that resolves into true or false, reflecting session dirty state.
+ */
+export function getSessionDirtyFlag(db, sessionId) {
+    return dbGet(db, "SELECT DIRTY FROM SESSION WHERE SESSION_ID = ?", [sessionId])
+        .then(row => {
+            if ( row == null ) {
+                reject()
+            } else {
+                return Promise.resolve(row.DIRTY)
+            }
+        })
+}
+
+/**
+ * Executes the query for the dirty flag with a callback, not a promise.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} windowId
+ * @param {*} fn
+ */
+export function getWindowDirtyFlagWithCallback(db, windowId, fn) {
+    db.get("SELECT DIRTY FROM SESSION WHERE SESSION_WINID = ?", [windowId], (err, row) => {
+        if (err) {
+            fn(false)
+        } else {
+            fn(row.DIRTY)
+        }
+    })
+}
+
+/**
+ * Resolves into a session id, obtained from window id.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} windowId
+ * @returns A promise that resolves into an object containing sessionId, sessionKey and creationTime.
+ */
+export function getSessionIdFromWindowdId(db, windowId) {
+    return dbGet(db, "SELECT SESSION_ID, SESSION_KEY, CREATION_TIME FROM SESSION WHERE SESSION_WINID = ?", [windowId])
+        .then(row => {
+            if (row == null) {
+                reject()
+            } else {
+                return Promise.resolve({
+                    sessionId: row.SESSION_ID,
+                    sessionKey: row.SESSION_KEY,
+                    creationTime: row.CREATION_TIME
+                })
+            }
+        })
+}
+
+/**
+ * Returns a promise that will resolve into a sessionID created from a query.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionKey
+ * @param {*} windowId
+ * @returns promise that resolves into a session id.
+ */
+export function ensureZapSessionId(db, sessionKey, windowId) {
+    return dbGet(db, "SELECT SESSION_ID FROM SESSION WHERE SESSION_KEY = ?", [sessionKey])
+        .then(row => {
+            if (row == null) {
+                return dbInsert(db, "INSERT INTO SESSION (SESSION_KEY, SESSION_WINID, CREATION_TIME) VALUES (?,?,?)", [sessionKey, windowId, Date.now()])
+            } else {
+                return Promise.resolve(row.SESSION_ID)
+            }
+        })
+}
+
+/**
+ * Promises to delete a session from the database, including all the rows that have the session as a foreign key.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @returns A promise of a removal of session.
+ */
+export function deleteSession(db, sessionId) {
+    return dbRemove(db, "DELETE FROM SESSION WHERE SESSION_ID = ?", [sessionId])
+}
+
diff --git a/src-electron/db/query.js b/src-electron/db/query-zcl.js
similarity index 50%
rename from src-electron/db/query.js
rename to src-electron/db/query-zcl.js
index 2f768083..aa970e7f 100644
--- a/src-electron/db/query.js
+++ b/src-electron/db/query-zcl.js
@@ -1,40 +1,19 @@
 // Copyright (c) 2020 Silicon Labs. All rights reserved.
 
 /** 
- * Contains all the application queries.
+ * This module provides queries for ZCL static queries.
  * 
- * @module JS API: database queries
+ * @module DB API: zcl database access
  */
-import { dbAll, dbGet, dbInsert, dbMultiInsert, dbRemove, dbUpdate } from './db-api.js'
-
-
-export function forPathCrc(db, path, crcCallback, noneCallback) {
-    dbGet(db, "SELECT PACKAGE_ID, PATH, CRC FROM PACKAGE WHERE PATH = ?", [path]).then(row => {
-        if (row == null) {
-            noneCallback()
-        } else {
-            crcCallback(row.CRC, row.PACKAGE_ID)
-        }
-    })
-}
-
-export function getPathCrc(db, path) {
-    return dbGet(db, "SELECT CRC FROM PACKAGE WHERE PATH = ?", [path]).then(row => new Promise((resolve, reject) => {
-        if (row == null) {
-            resolve(null)
-        } else {
-            resolve(row.CRC)
-        }
-    }))
-}
-export function insertPathCrc(db, path, crc) {
-    return dbInsert(db, "INSERT INTO PACKAGE ( PATH, CRC ) VALUES (?, ?)", [path, crc])
-}
-
-export function updatePathCrc(db, path, crc) {
-    return dbInsert(db, "UPDATE PACKAGE SET CRC = ? WHERE PATH = ?", [path, crc])
-}
+import { dbAll, dbGet, dbMultiInsert, dbUpdate, dbInsert } from './db-api.js';
 
+/**
+ * Retrieves all the enums in the database.
+ *
+ * @export
+ * @param {*} db
+ * @returns Promise that resolves with the rows of enums.
+ */
 export function selectAllEnums(db) {
     return dbAll(db, 'SELECT ENUM_ID, NAME, TYPE FROM ENUM ORDER BY NAME', [])
 }
@@ -51,6 +30,13 @@ export function selectEnumById(db, id) {
     return dbGet(db, 'SELECT ENUM_ID, NAME, TYPE FROM ENUM WHERE ENUM_ID = ? ORDER BY NAME', [id])
 }
 
+/**
+ * Retrieves all the bitmaps in the database.
+ *
+ * @export
+ * @param {*} db
+ * @returns Promise that resolves with the rows of bitmaps.
+ */
 export function selectAllBitmaps(db) {
     return dbAll(db, 'SELECT BITMAP_ID, NAME, TYPE FROM BITMAP ORDER BY NAME', [])
 }
@@ -63,6 +49,13 @@ export function selectBitmapById(db, id) {
     return dbGet(db, 'SELECT BITMAP_ID, NAME, TYPE FROM BITMAP WHERE BITMAP_ID = ? ORDER BY NAME', [id])
 }
 
+/**
+ * Retrieves all the domains in the database.
+ *
+ * @export
+ * @param {*} db
+ * @returns Promise that resolves with the rows of domains.
+ */
 export function selectAllDomains(db) {
     return dbAll(db, 'SELECT DOMAIN_ID, NAME FROM DOMAIN ORDER BY NAME', [])
 }
@@ -71,6 +64,13 @@ export function selectDomainById(db, id) {
     return dbGet(db, 'SELECT DOMAIN_ID, NAME FROM DOMAIN WHERE DOMAIN_ID = ? ORDER BY NAME', [id])
 }
 
+/**
+ * Retrieves all the structs in the database.
+ *
+ * @export
+ * @param {*} db
+ * @returns Promise that resolves with the rows of structs.
+ */
 export function selectAllStructs(db) {
     return dbAll(db, 'SELECT STRUCT_ID, NAME FROM STRUCT ORDER BY NAME', [])
 }
@@ -79,6 +79,21 @@ export function selectStructById(db, id) {
     return dbGet(db, 'SELECT STRUCT_ID, NAME FROM STRUCT WHERE STRUCT_ID = ? ORDER BY NAME', [id])
 }
 
+export function selectAllStructItems(db) {
+    return dbAll(db, 'SELECT NAME, TYPE, STRUCT_REF FROM STRUCT_ITEM ORDER BY STRUCT_REF', []);
+}
+
+export function selectStructItemById(db, id) {
+    return dbAll(db, 'SELECT NAME FROM STRUCT_ITEM WHERE STRUCT_REF=?', [id]);
+}
+
+/**
+ * Retrieves all the clusters in the database.
+ *
+ * @export
+ * @param {*} db
+ * @returns Promise that resolves with the rows of clusters.
+ */
 export function selectAllClusters(db) {
     return dbAll(db, 'SELECT CLUSTER_ID, CODE, MANUFACTURER_CODE, NAME, DESCRIPTION, DEFINE FROM CLUSTER ORDER BY CODE', [])
 }
@@ -87,6 +102,13 @@ export function selectClusterById(db, id) {
     return dbGet(db, 'SELECT CLUSTER_ID, CODE, MANUFACTURER_CODE, NAME, DESCRIPTION FROM CLUSTER WHERE CLUSTER_ID = ?', [id])
 }
 
+/**
+ * Retrieves all the device types in the database.
+ *
+ * @export
+ * @param {*} db
+ * @returns Promise that resolves with the rows of device types.
+ */
 export function selectAllDeviceTypes(db) {
     return dbAll(db, 'SELECT DEVICE_TYPE_ID, CODE, PROFILE_ID, NAME, DESCRIPTION FROM DEVICE_TYPE ORDER BY CODE', [])
 }
@@ -95,23 +117,71 @@ export function selectDeviceTypeById(db, id) {
     return dbGet(db, 'SELECT DEVICE_TYPE_ID, CODE, PROFILE_ID, NAME, DESCRIPTION FROM DEVICE_TYPE WHERE DEVICE_TYPE_ID = ?', [id])
 }
 
-export function selectCountFrom(db, table) {
-    return dbGet(db, `SELECT COUNT(*) FROM ${table}`).then(x => x['COUNT(*)'])
+export function selectAttributesByClusterId(db, clusterId) {
+    return dbAll(db, `SELECT ATTRIBUTE_ID, CLUSTER_REF, CODE, MANUFACTURER_CODE, NAME, TYPE, SIDE, DEFINE, MIN, MAX, IS_WRITABLE, DEFAULT_VALUE, IS_OPTIONAL, IS_REPORTABLE FROM ATTRIBUTE WHERE CLUSTER_REF = ? ORDER BY CODE`, [clusterId])
 }
 
-export function selectAttributesByClusterId(db, clusterId) {
-    return dbAll(db, `SELECT ATTRIBUTE_ID, CLUSTER_REF, CODE, MANUFACTURER_CODE, NAME, TYPE, SIDE, DEFINE, MIN, MAX, IS_WRITABLE, DEFAULT_VALUE, IS_OPTIONAL FROM ATTRIBUTE WHERE CLUSTER_REF = ? ORDER BY CODE`, [clusterId])
+export function selectAttributeByAttributeRef(db, attributeRef) {
+    return dbGet(db, 'SELECT ATTRIBUTE_ID, CLUSTER_REF, CODE, MANUFACTURER_CODE, NAME, TYPE, SIDE, DEFINE, MIN, MAX, IS_WRITABLE, DEFAULT_VALUE, IS_OPTIONAL, IS_REPORTABLE FROM ATTRIBUTE WHERE ATTRIBUTE_ID = ?', attributeRef)
+}
+
+export function selectAllAttributes(db) {
+    return dbAll(db, `SELECT ATTRIBUTE_ID, CLUSTER_REF, CODE, MANUFACTURER_CODE, NAME, TYPE, SIDE, DEFINE, MIN, MAX, IS_WRITABLE, DEFAULT_VALUE, IS_OPTIONAL, IS_REPORTABLE FROM ATTRIBUTE ORDER BY CODE`, [])
 }
 
 export function selectCommandsByClusterId(db, clusterId) {
     return dbAll(db, `SELECT COMMAND_ID, CLUSTER_REF, CODE, MANUFACTURER_CODE, NAME, DESCRIPTION, SOURCE, IS_OPTIONAL FROM COMMAND WHERE CLUSTER_REF = ? ORDER BY CODE`, [clusterId])
 }
 
+export function selectAllCommands(db) {
+    return dbAll(db, `SELECT COMMAND_ID, CLUSTER_REF, CODE, MANUFACTURER_CODE, NAME, DESCRIPTION, SOURCE, IS_OPTIONAL FROM COMMAND ORDER BY CODE`, [])
+}
+
+export function selectEndpointTypeClustersByEndpointTypeId(db, endpointTypeId) {
+    return dbAll(db, `SELECT ENDPOINT_TYPE_REF, CLUSTER_REF, SIDE, ENABLED FROM ENDPOINT_TYPE_CLUSTER WHERE ENDPOINT_TYPE_REF = ? ORDER BY CLUSTER_REF`, [endpointTypeId])
+}
+
+export function selectEndpointTypeAttributesByEndpointId(db, endpointTypeId) {
+    return dbAll(db, `SELECT ENDPOINT_TYPE_REF, ATTRIBUTE_REF, INCLUDED, EXTERNAL, FLASH, SINGLETON, BOUNDED, DEFAULT_VALUE FROM ENDPOINT_TYPE_ATTRIBUTE WHERE ENDPOINT_TYPE_REF = ? ORDER BY ATTRIBUTE_REF`, [endpointTypeId])
+}
+
+export function selectEndpointTypeCommandsByEndpointId(db, endpointTypeId) {
+    return dbAll(db, `SELECT ENDPOINT_TYPE_REF, COMMAND_REF, INCOMING, OUTGOING FROM ENDPOINT_TYPE_COMMAND WHERE ENDPOINT_TYPE_REF = ? ORDER BY COMMAND_REF`, [endpointTypeId])
+}
+
+export function selectEndpointTypeReportableAttributeByEndpointId(db, endpointTypeId) {
+    return dbAll(db, `SELECT ENDPOINT_TYPE_REF, ATTRIBUTE_REF, INCLUDED, MIN_INTERVAL, MAX_INTERVAL, REPORTABLE_CHANGE FROM ENDPOINT_TYPE_REPORTABLE_ATTRIBUTE WHERE ENDPOINT_TYPE_REF = ? ORDER BY ATTRIBUTE_REF`, [endpointTypeId])
+}
+
+export function selectDeviceTypeClustersByDeviceTypeRef(db, deviceTypeRef) {
+    return dbAll(db, `SELECT DEVICE_TYPE_CLUSTER_ID, DEVICE_TYPE_REF, CLUSTER_REF, CLUSTER_NAME, INCLUDE_CLIENT, INCLUDE_SERVER, LOCK_CLIENT, LOCK_SERVER FROM DEVICE_TYPE_CLUSTER WHERE DEVICE_TYPE_REF = ? ORDER BY CLUSTER_REF`, [deviceTypeRef])
+}
+
+export function selectDeviceTypeAttributesByDeviceTypeClusterRef(db, deviceTypeClusterRef) {
+    return dbAll(db, `SELECT DEVICE_TYPE_CLUSTER_REF, ATTRIBUTE_REF, ATTRIBUTE_NAME FROM DEVICE_TYPE_ATTRIBUTE WHERE DEVICE_TYPE_CLUSTER_REF = ? ORDER BY ATTRIBUTE_REF`, [deviceTypeClusterRef])
+}
+
+export function selectDeviceTypeCommandsByDeviceTypeClusterRef(db, deviceTypeClusterRef) {
+    return dbAll(db, `SELECT DEVICE_TYPE_CLUSTER_REF, COMMAND_REF, COMMAND_NAME FROM DEVICE_TYPE_COMMAND WHERE DEVICE_TYPE_CLUSTER_REF = ? ORDER BY COMMAND_REF`, [deviceTypeClusterRef])
+}
+
+export function selectDeviceTypeAttributesByDeviceTypeRef(db, deviceTypeRef) {
+    return dbAll(db, `SELECT DEVICE_TYPE_CLUSTER.CLUSTER_REF, DEVICE_TYPE_ATTRIBUTE.DEVICE_TYPE_CLUSTER_REF, DEVICE_TYPE_ATTRIBUTE.ATTRIBUTE_REF, DEVICE_TYPE_ATTRIBUTE.ATTRIBUTE_NAME FROM DEVICE_TYPE_ATTRIBUTE, DEVICE_TYPE_CLUSTER WHERE DEVICE_TYPE_CLUSTER.DEVICE_TYPE_REF = ? AND DEVICE_TYPE_CLUSTER.DEVICE_TYPE_CLUSTER_ID = DEVICE_TYPE_ATTRIBUTE.DEVICE_TYPE_CLUSTER_REF`, [deviceTypeRef])
+}
 
-// Inserts clusters into the database.
-// data is an array of objects that must contain: code, name, description, define
-// It also contains commands: and attributes:
-//
+export function selectDeviceTypeCommandsByDeviceTypeRef(db, deviceTypeRef) {
+    return dbAll(db, `SELECT DEVICE_TYPE_CLUSTER.CLUSTER_REF, DEVICE_TYPE_COMMAND.DEVICE_TYPE_CLUSTER_REF, DEVICE_TYPE_COMMAND.COMMAND_REF, DEVICE_TYPE_COMMAND.COMMAND_NAME FROM DEVICE_TYPE_COMMAND, DEVICE_TYPE_CLUSTER WHERE DEVICE_TYPE_CLUSTER.DEVICE_TYPE_REF = ? AND DEVICE_TYPE_CLUSTER.DEVICE_TYPE_CLUSTER_ID = DEVICE_TYPE_COMMAND.DEVICE_TYPE_CLUSTER_REF`, [deviceTypeRef])
+}
+
+/**
+ * Inserts clusters into the database.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} packageId
+ * @param {*} data an array of objects that must contain: code, name, description, define. It also contains commands: and attributes:
+ * @returns Promise of cluster insertion.
+ */
 export function insertClusters(db, packageId, data) {
     return dbMultiInsert(db, "INSERT INTO CLUSTER (PACKAGE_REF, CODE, NAME, DESCRIPTION, DEFINE) VALUES (?, ?, ?, ?, ?)", data.map(cluster => [packageId, cluster.code, cluster.name, cluster.description, cluster.define]))
         .then(lastIdsArray => {
@@ -140,7 +210,8 @@ export function insertClusters(db, packageId, data) {
                         attribute.max,
                         attribute.isWritable,
                         attribute.defaultValue,
-                        attribute.isOptional
+                        attribute.isOptional,
+                        attribute.isReportable
                     ]))
                 }
             }
@@ -160,14 +231,21 @@ export function insertClusters(db, packageId, data) {
                         argsToLoad)
                 })
             var pAttribute = dbMultiInsert(db,
-                "INSERT INTO ATTRIBUTE (CLUSTER_REF, CODE, NAME, TYPE, SIDE, DEFINE, MIN, MAX, IS_WRITABLE, DEFAULT_VALUE, IS_OPTIONAL) VALUES (?,?,?,?,?,?,?,?,?,?,?)",
+                "INSERT INTO ATTRIBUTE (CLUSTER_REF, CODE, NAME, TYPE, SIDE, DEFINE, MIN, MAX, IS_WRITABLE, DEFAULT_VALUE, IS_OPTIONAL, IS_REPORTABLE) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)",
                 attributesToLoad)
             return Promise.all([pCommand, pAttribute])
         })
 }
 
-// Inserts device types into the database.
-// data is an array of objects that must contain: code, name, description
+/**
+ * Inserts device types into the database.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} packageId
+ * @param {*} data an array of objects that must contain: code, name, description
+ * @returns Promise of an insertion of device types.
+ */
 export function insertDeviceTypes(db, packageId, data) {
     return dbMultiInsert(db, "INSERT INTO DEVICE_TYPE (PACKAGE_REF, CODE, PROFILE_ID, NAME, DESCRIPTION) VALUES (?, ?, ?, ?, ?)", data.map(dt => {
         return [packageId, dt.code, dt.profileId, dt.name, dt.description]
@@ -178,17 +256,81 @@ export function insertDeviceTypes(db, packageId, data) {
             if ('clusters' in data[i]) {
                 var lastId = lastIdsArray[i]
                 var clusters = data[i].clusters
-                itemsToLoad.push(...clusters.map(cluster => [lastId, cluster.clusterName, cluster.client, cluster.server, cluster.clientLocked, cluster.serverLocked]))
+                // This is an array that links the generated deviceTyepRef to the cluster via generating an array of arrays, 
+                var zclIdsPromises = Promise.all(clusters.map( cluster => {
+                    return dbInsert(db, 
+                                'INSERT INTO DEVICE_TYPE_CLUSTER (DEVICE_TYPE_REF, CLUSTER_NAME, INCLUDE_CLIENT, INCLUDE_SERVER, LOCK_CLIENT, LOCK_SERVER) VALUES (?,?,?,?,?,?)',
+                                [lastId, cluster.clusterName, cluster.client, cluster.server, cluster.clientLocked, cluster.serverLocked],
+                                true).then( deviceTypeClusterRef => {
+                                    return   {
+                                                dtClusterRef: deviceTypeClusterRef, 
+                                                clusterData: cluster
+                                            }
+                                })
+                }))
+
+                zclIdsPromises.then(dtClusterRefDataPairs => {
+                    insertDeviceTypeAttributes(db, dtClusterRefDataPairs)
+                    insertDeviceTypeCommands(db, dtClusterRefDataPairs)
+                })
             }
         }
-        return dbMultiInsert(db,
-            'INSERT INTO DEVICE_TYPE_CLUSTER (DEVICE_TYPE_REF, CLUSTER_NAME, INCLUDE_CLIENT, INCLUDE_SERVER, LOCK_CLIENT, LOCK_SERVER) VALUES (?,?,?,?,?,?)',
-            itemsToLoad)
+        return zclIdsPromises
     })
 }
 
+/**
+ * This handles the loading of device type attribute requirements into the database. 
+ * There is a need to post-process to attach the actual attribute ref after the fact
+ * @param {*} db 
+ * @param {*} dtClusterRefDataPairs 
+ */
+export function insertDeviceTypeAttributes(db, dtClusterRefDataPairs) {
+    var attributes = []
+    dtClusterRefDataPairs.map(dtClusterRefDataPair => {
+        var dtClusterRef = dtClusterRefDataPair.dtClusterRef
+        var clusterData = dtClusterRefDataPair.clusterData
+        if ( 'requiredAttributes' in clusterData) {
+            clusterData.requiredAttributes.forEach(attributeName => {
+                attributes.push([dtClusterRef, attributeName])
+            })
+        }
+    })
+    return dbMultiInsert(db, 'INSERT INTO DEVICE_TYPE_ATTRIBUTE (DEVICE_TYPE_CLUSTER_REF, ATTRIBUTE_NAME) VALUES (?, ?)',
+                            attributes)
+}
+
+/**
+ * This handles the loading of device type command requirements into the database. 
+ * There is a need to post-process to attach the actual command ref after the fact
+ * @param {*} db 
+ * @param {*} dtClusterRefDataPairs 
+ */
+export function insertDeviceTypeCommands(db, dtClusterRefDataPairs) {
+    var commands= []
+    dtClusterRefDataPairs.map(dtClusterRefDataPair => {
+        var dtClusterRef = dtClusterRefDataPair.dtClusterRef
+        var clusterData = dtClusterRefDataPair.clusterData
+        if ( 'requiredCommands' in clusterData) {
+            clusterData.requiredCommands.forEach(commandName => {
+                commands.push([dtClusterRef, commandName])
+            })
+        }
+    })
+    return dbMultiInsert(db, 'INSERT INTO DEVICE_TYPE_COMMAND (DEVICE_TYPE_CLUSTER_REF, COMMAND_NAME) VALUES (?, ?)',
+                            commands)
+}
+
 export function updateClusterReferencesForDeviceTypeClusters(db) {
-    return dbUpdate(db, 'UPDATE DEVICE_TYPE_CLUSTER SET CLUSTER_REF = (SELECT CLUSTER.CLUSTER_ID FROM CLUSTER WHERE CLUSTER.NAME = DEVICE_TYPE_CLUSTER.CLUSTER_NAME)', [])
+    return dbUpdate(db, 'UPDATE DEVICE_TYPE_CLUSTER SET CLUSTER_REF = (SELECT CLUSTER.CLUSTER_ID FROM CLUSTER WHERE lower(CLUSTER.NAME) = lower(DEVICE_TYPE_CLUSTER.CLUSTER_NAME))', [])
+}
+
+export function updateAttributeReferencesForDeviceTypeReferences(db) {
+    return dbUpdate(db, 'UPDATE DEVICE_TYPE_ATTRIBUTE SET ATTRIBUTE_REF = (SELECT ATTRIBUTE.ATTRIBUTE_ID FROM ATTRIBUTE WHERE upper(ATTRIBUTE.DEFINE) = upper(DEVICE_TYPE_ATTRIBUTE.ATTRIBUTE_NAME))', [])
+}
+
+export function updateCommandReferencesForDeviceTypeReferences(db) {
+    return dbUpdate(db, 'UPDATE DEVICE_TYPE_COMMAND SET COMMAND_REF = (SELECT COMMAND.COMMAND_ID FROM COMMAND WHERE upper(COMMAND.NAME) = upper(DEVICE_TYPE_COMMAND.COMMAND_NAME))', [])
 }
 
 /**
@@ -238,8 +380,15 @@ export function insertStructs(db, packageId, data) {
     })
 }
 
-// Inserts enums into the database.
-// data is an array of objects that must contain: name, type
+/**
+ * Inserts enums into the database.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} packageId
+ * @param {*} data an array of objects that must contain: name, type
+ * @returns A promise of enum insertion.
+ */
 export function insertEnums(db, packageId, data) {
     return dbMultiInsert(db, "INSERT INTO ENUM (PACKAGE_REF, NAME, TYPE) VALUES (?, ?, ?)", data.map(en => {
         return [packageId, en.name, en.type]
@@ -285,246 +434,3 @@ export function insertBitmaps(db, packageId, data) {
                 fieldsToLoad)
         })
 }
-
-/************************** SESSION QUERIES *************************************/
-
-/**
- * Promises to delete a session from the database, including all the rows that have the session as a foreign key.
- *
- * @export
- * @param {*} db
- * @param {*} sessionId
- * @returns A promise of a removal of session.
- */
-export function deleteSession(db, sessionId) {
-    return dbRemove(db, "DELETE FROM SESSION WHERE SESSION_ID = ?", [sessionId])
-}
-
-/**
- * Promises to update or insert a key/value pair in SESSION_KEY_VALUE table.
- *
- * @export
- * @param {*} db
- * @param {*} sessionId
- * @param {*} key
- * @param {*} value
- * @returns A promise of creating or updating a row, resolves with the rowid of a new row.
- */
-export function updateKeyValue(db, sessionId, key, value) {
-    return dbInsert(db, "INSERT OR REPLACE INTO SESSION_KEY_VALUE (SESSION_REF, KEY, VALUE) VALUES (?,?,?)", [sessionId, key, value])
-}
-/**
- * Promises to update the cluster include/exclude state.
- *
- * @export
- * @param {*} db
- * @param {*} endpointTypeId
- * @param {*} clusterId
- * @param {*} side 
- * @param {*} enabled
- * @returns Promise to update the cluster exclude/include state.
- */
-export function insertOrReplaceClusterState(db, endpointTypeId, clusterId, side, enabled) {
-    return dbInsert(db, "INSERT OR REPLACE INTO ENDPOINT_TYPE_CLUSTER ( ENDPOINT_TYPE_REF, CLUSTER_REF, SIDE, ENABLED ) VALUES ( ?, ?, ?, ?)", [endpointTypeId, clusterId, side, enabled])
-}
-
-/*
-  Resolves into all the cluster states.
-*/
-export function getAllEndpointTypeClusterState(db, endpointTypeId) {
-    return dbAll(db, "SELECT CLUSTER.NAME, CLUSTER.CODE, CLUSTER.MANUFACTURER_CODE, ENDPOINT_TYPE_CLUSTER.SIDE, ENDPOINT_TYPE_CLUSTER.ENABLED FROM ENDPOINT_TYPE_CLUSTER INNER JOIN CLUSTER WHERE ENDPOINT_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID AND ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF = ?", [endpointTypeId])
-        .then((rows) => new Promise((resolve, reject) => {
-            if (rows == null) {
-                resolve([])
-            } else {
-                var result = rows.map(row => {
-                    var obj = {
-                        clusterName: row.NAME,
-                        clusterCode: row.CODE,
-                        side: row.SIDE,
-                        enabled: (row.STATE == '1')
-                    }
-                    if (row.MANUFACTURER_CODE != null)
-                        obj.manufacturerCode = row.MANUFACTURER_CODE;
-                    return obj
-                })
-                resolve(result)
-            }
-        }))
-}
-
-/**
-* Promises to add an endpoint. 
-*
-* @export
-* @param {*} db
-* @param {*} sessionId
-* @param {*} endpointId
-* @param {*} endpointTypeRef
-* @param {*} networkId
-* @returns Promise to update endpoints. 
-*/
-export function insertEndpoint(db, sessionId, endpointId, endpointTypeRef, networkId) {
-    return dbInsert(db, "INSERT OR REPLACE INTO ENDPOINT ( SESSION_REF, ENDPOINT_ID, ENDPOINT_TYPE_REF, NETWORK_ID ) VALUES ( ?, ?, ?, ?)", [sessionId, endpointId, endpointTypeRef, networkId])
-}
-
-/**
- * Deletes an endpoint.
- *
- * @export
- * @param {*} db
- * @param {*} id
- * @returns Promise to delete an endpoint that resolves with the number of rows that were deleted.
- */
-export function deleteEndpoint(db, id) {
-    return dbRemove(db, "DELETE FROM ENDPOINT WHERE ENDPOINT_REF = ?", [id])
-}
-
-/**
-* Promises to add an endpoint type. 
-*
-* @export
-* @param {*} db
-* @param {*} sessionId
-* @param {*} name
-* @param {*} deviceTypeRef
-* @returns Promise to update endpoints. 
-*/
-export function insertEndpointType(db, sessionId, name, deviceTypeRef) {
-    return dbInsert(db, "INSERT OR REPLACE INTO ENDPOINT_TYPE ( SESSION_REF, NAME, DEVICE_TYPE_REF ) VALUES ( ?, ?, ?)", [sessionId, name, deviceTypeRef])
-}
-
-/**
- * Promise to delete an endpoint type. 
- * @param {*} db 
- * @param {*} sessionId 
- * @param {*} id 
- */
-
-export function deleteEndpointType(db, id) {
-    return dbRemove(db, "DELETE FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = ?", [id])
-}
-
-
-
-/**
- * Resolves to an array of objects that contain 'key' and 'value'
- *
- * @export
- * @param {*} db
- * @param {*} sessionId
- * @returns Promise to retrieve all session key values.
- */
-export function getAllSesionKeyValues(db, sessionId) {
-    return dbAll(db, "SELECT KEY, VALUE FROM SESSION_KEY_VALUE WHERE SESSION_REF = ? ORDER BY KEY", [sessionId])
-        .then((rows) => new Promise((resolve, reject) => {
-            if (rows == null) {
-                resolve([])
-            } else {
-                var result = rows.map(row => {
-                    return {
-                        key: row.KEY,
-                        value: row.VALUE
-                    }
-                })
-                resolve(result)
-            }
-        }))
-}
-/**
- * Resolves to an array of endpoint types.
- *
- * @export
- * @param {*} db
- * @param {*} sessionId
- * @returns Promise to retrieve all endpoint types.
- */
-export function getAllEndpointTypes(db, sessionId) {
-    return dbAll(db, "SELECT NAME, DEVICE_TYPE_REF FROM ENDPOINT_TYPE WHERE SESSION_REF = ? ORDER BY NAME", [sessionId])
-        .then((rows) => new Promise((resolve, reject) => {
-            if (rows == null) {
-                resolve([])
-            } else {
-                var result = rows.map(rows => {
-                    return {
-                        name: row.NAME
-                    }
-                })
-                resolve(result)
-            }
-        }))
-}
-
-/**
- * Returns a promise that resolves into an array of objects containing 'sessionId', 'sessionKey' and 'creationTime'.
- *
- * @export
- * @param {*} db
- * @returns A promise of executing a query.
- */
-export function getAllSessions(db) {
-    return dbAll(db, "SELECT SESSION_ID, SESSION_KEY, CREATION_TIME FROM SESSION", [])
-        .then(rows => {
-            if (rows == null) {
-                reject()
-            } else {
-                var map = rows.map(row => {
-                    return {
-                        sessionId: row.SESSION_ID,
-                        sessionKey: row.SESSION_KEY,
-                        creationTime: row.CREATION_TIME
-                    }
-                })
-                return Promise.resolve(map)
-            }
-        })
-}
-
-export function setSessionClean(db, sessionId) {
-    return dbUpdate(db, "UPDATE SESSION SET DIRTY = ? WHERE SESSION_ID = ?", [0, sessionId])
-}
-/**
- * Resolves with true or false, depending whether this session is dirty.
- *
- * @export
- * @param {*} db
- * @param {*} sessionId
- * @returns A promise that resolves into true or false, reflecting session dirty state.
- */
-export function getSessionDirtyFlag(db, sessionId) {
-    return dbGet(db, "SELECT DIRTY FROM SESSION WHERE SESSION_ID = ?", [sessionId])
-        .then(row => {
-            if ( row == null ) {
-                reject()
-            } else {
-                return Promise.resolve(row.DIRTY)
-            }
-        })
-}
-
-export function getSessionIdFromWindowdId(db, windowId) {
-    return dbGet(db, "SELECT SESSION_ID, SESSION_KEY, CREATION_TIME FROM SESSION WHERE SESSION_WINID = ?", [windowId])
-        .then(row => {
-            if (row == null) {
-                reject()
-            } else {
-                return Promise.resolve({
-                    sessionId: row.SESSION_ID,
-                    sessionKey: row.SESSION_KEY,
-                    creationTime: row.CREATION_TIME
-                })
-            }
-        })
-}
-
-export function ensureZapSessionId(db, sessionKey, windowId) {
-    return dbGet(db, "SELECT SESSION_ID FROM SESSION WHERE SESSION_KEY = ?", [sessionKey])
-        .then(row => {
-            if (row == null) {
-                return dbInsert(db, "INSERT INTO SESSION (SESSION_KEY, SESSION_WINID, CREATION_TIME) VALUES (?,?,?)", [sessionKey, windowId, Date.now()])
-            } else {
-                return Promise.resolve(row.SESSION_ID)
-            }
-        })
-}
-
diff --git a/src-electron/db/zap-schema.sql b/src-electron/db/zap-schema.sql
index e399a7d2..c75262ca 100644
--- a/src-electron/db/zap-schema.sql
+++ b/src-electron/db/zap-schema.sql
@@ -1,3 +1,21 @@
+/*
+
+$$$$$$$\                     $$\                                              
+$$  __$$\                    $$ |                                             
+$$ |  $$ |$$$$$$\   $$$$$$$\ $$ |  $$\ $$$$$$\   $$$$$$\   $$$$$$\   $$$$$$$\ 
+$$$$$$$  |\____$$\ $$  _____|$$ | $$  |\____$$\ $$  __$$\ $$  __$$\ $$  _____|
+$$  ____/ $$$$$$$ |$$ /      $$$$$$  / $$$$$$$ |$$ /  $$ |$$$$$$$$ |\$$$$$$\  
+$$ |     $$  __$$ |$$ |      $$  _$$< $$  __$$ |$$ |  $$ |$$   ____| \____$$\ 
+$$ |     \$$$$$$$ |\$$$$$$$\ $$ | \$$\\$$$$$$$ |\$$$$$$$ |\$$$$$$$\ $$$$$$$  |
+\__|      \_______| \_______|\__|  \__|\_______| \____$$ | \_______|\_______/ 
+                                                $$\   $$ |                    
+                                                \$$$$$$  |                    
+                                                 \______/                     
+
+You can create these giant separators via:
+http://patorjk.com/software/taag/#p=display&f=Big%20Money-nw
+*/
+
 /*
   PACKAGE table contains the "packages" that are the sources for the
   loading of the other data. They may be individual files, or
@@ -10,6 +28,18 @@ CREATE TABLE IF NOT EXISTS "PACKAGE" (
   "PATH" text NOT NULL UNIQUE,
   "CRC" integer
 );
+
+
+/*
+ $$$$$$\    $$\                $$\     $$\                       $$\            $$\               
+$$  __$$\   $$ |               $$ |    \__|                      $$ |           $$ |              
+$$ /  \__|$$$$$$\    $$$$$$\ $$$$$$\   $$\  $$$$$$$\        $$$$$$$ | $$$$$$\ $$$$$$\    $$$$$$\  
+\$$$$$$\  \_$$  _|   \____$$\\_$$  _|  $$ |$$  _____|      $$  __$$ | \____$$\\_$$  _|   \____$$\ 
+ \____$$\   $$ |     $$$$$$$ | $$ |    $$ |$$ /            $$ /  $$ | $$$$$$$ | $$ |     $$$$$$$ |
+$$\   $$ |  $$ |$$\ $$  __$$ | $$ |$$\ $$ |$$ |            $$ |  $$ |$$  __$$ | $$ |$$\ $$  __$$ |
+\$$$$$$  |  \$$$$  |\$$$$$$$ | \$$$$  |$$ |\$$$$$$$\       \$$$$$$$ |\$$$$$$$ | \$$$$  |\$$$$$$$ |
+ \______/    \____/  \_______|  \____/ \__| \_______|       \_______| \_______|  \____/  \_______|
+*/
 /*
   CLUSTER table contains the clusters loaded from the ZCL XML files.
 */
@@ -64,6 +94,7 @@ CREATE TABLE IF NOT EXISTS "ATTRIBUTE" (
   "IS_WRITABLE" integer,
   "DEFAULT_VALUE" text,
   "IS_OPTIONAL" integer,
+  "IS_REPORTABLE" integer,
   foreign key (CLUSTER_REF) references CLUSTER(CLUSTER_ID)
 );
 /*
@@ -145,9 +176,10 @@ CREATE TABLE IF NOT EXISTS "DEVICE_TYPE" (
 );
 
 /*
-   DEVICE_TYPE_CLUSTER contains clusters that belong to the device type.
+  DEVICE_TYPE_CLUSTER contains clusters that belong to the device type.
  */
 CREATE TABLE IF NOT EXISTS "DEVICE_TYPE_CLUSTER" (
+  "DEVICE_TYPE_CLUSTER_ID" integer primary key autoincrement,
   "DEVICE_TYPE_REF" integer,
   "CLUSTER_REF" integer,
   "CLUSTER_NAME" text,
@@ -158,6 +190,41 @@ CREATE TABLE IF NOT EXISTS "DEVICE_TYPE_CLUSTER" (
   foreign key (DEVICE_TYPE_REF) references DEVICE_TYPE(DEVICE_TYPE_ID),
   foreign key (CLUSTER_REF) references CLUSTER(CLUSTER_ID)
 );
+
+/*
+  DEVICE_TYPE_ATTRIBUTE contains attribuets that belong to a device type cluster. 
+*/
+CREATE TABLE IF NOT EXISTS "DEVICE_TYPE_ATTRIBUTE" (
+  "DEVICE_TYPE_CLUSTER_REF" integer,
+  "ATTRIBUTE_REF" integer, 
+  "ATTRIBUTE_NAME" text,
+  foreign key (DEVICE_TYPE_CLUSTER_REF) references DEVICE_TYPE_CLUSTER(DEVICE_TYPE_CLUSTER_ID),
+  foreign key (ATTRIBUTE_REF) references ATTRIBUTE(ATTRIBUTE_ID)
+);
+
+/*
+  DEVICE_TYPE_COMMAND contains attribuets that belong to a device type cluster. 
+*/
+CREATE TABLE IF NOT EXISTS "DEVICE_TYPE_COMMAND" (
+  "DEVICE_TYPE_CLUSTER_REF" integer,
+  "COMMAND_REF" integer, 
+  "COMMAND_NAME" text,
+  foreign key (DEVICE_TYPE_CLUSTER_REF) references DEVICE_TYPE_CLUSTER(DEVICE_TYPE_CLUSTER_ID),
+  foreign key (COMMAND_REF) references COMMAND(COMMAND_ID)
+);
+
+/*
+
+ $$$$$$\                                $$\                                 $$\            $$\               
+$$  __$$\                               \__|                                $$ |           $$ |              
+$$ /  \__| $$$$$$\   $$$$$$$\  $$$$$$$\ $$\  $$$$$$\  $$$$$$$\         $$$$$$$ | $$$$$$\ $$$$$$\    $$$$$$\  
+\$$$$$$\  $$  __$$\ $$  _____|$$  _____|$$ |$$  __$$\ $$  __$$\       $$  __$$ | \____$$\\_$$  _|   \____$$\ 
+ \____$$\ $$$$$$$$ |\$$$$$$\  \$$$$$$\  $$ |$$ /  $$ |$$ |  $$ |      $$ /  $$ | $$$$$$$ | $$ |     $$$$$$$ |
+$$\   $$ |$$   ____| \____$$\  \____$$\ $$ |$$ |  $$ |$$ |  $$ |      $$ |  $$ |$$  __$$ | $$ |$$\ $$  __$$ |
+\$$$$$$  |\$$$$$$$\ $$$$$$$  |$$$$$$$  |$$ |\$$$$$$  |$$ |  $$ |      \$$$$$$$ |\$$$$$$$ | \$$$$  |\$$$$$$$ |
+ \______/  \_______|\_______/ \_______/ \__| \______/ \__|  \__|       \_______| \_______|  \____/  \_______|
+*/
+
 /*
   SESSION table contains the list of known and remembered sessions.
   In case of electron SESSION_WINID is the window ID for a given
@@ -218,9 +285,166 @@ CREATE TABLE IF NOT EXISTS "ENDPOINT_TYPE_CLUSTER" (
   foreign key (ENDPOINT_TYPE_REF) references ENDPOINT_TYPE(ENDPOINT_TYPE_ID) on delete cascade,
   foreign key (CLUSTER_REF) references CLUSTER(CLUSTER_ID)
 );
+
+/*
+  ENDPOINT_TYPE_ATTRIBUTE table contains the user data configuration for the various parameters that exist
+  for an attribute on an endpoint. This essentially lets you determine if something should be included or not.
+*/
+CREATE TABLE IF NOT EXISTS "ENDPOINT_TYPE_ATTRIBUTE" (
+  "ENDPOINT_TYPE_REF" integer,
+  "ATTRIBUTE_REF" integer, 
+  "INCLUDED" integer, 
+  "EXTERNAL" integer, 
+  "FLASH" integer,
+  "SINGLETON" integer,
+  "BOUNDED" integer,
+  "DEFAULT_VALUE" text,
+  foreign key (ENDPOINT_TYPE_REF) references ENDPOINT_TYPE(ENDPOINT_TYPE_ID) on delete cascade,
+  foreign key (ATTRIBUTE_REF) references ATTRIBUTE(ATTRIBUTE_ID)
+);
+ 
+/*
+  ENDPOINT_TYPE_COMMAND table contains the user data configuration for the various parameters that exist
+  for commands on an endpoint. This essentially lets you determine if something should be included or not.
+*/
+CREATE TABLE IF NOT EXISTS "ENDPOINT_TYPE_COMMAND" (
+  "ENDPOINT_TYPE_REF" integer,
+  "COMMAND_REF" integer, 
+  "INCOMING" integer, 
+  "OUTGOING" integer, 
+  foreign key (ENDPOINT_TYPE_REF) references ENDPOINT_TYPE(ENDPOINT_TYPE_ID) on delete cascade,
+  foreign key (COMMAND_REF) references COMMAND(COMMAND_ID)
+);
+
+
+/*
+  ENDPOINT_TYPE_ATTRIBUTE_REPORTING table contains the user data configuration for each attribute reporting. 
+  This is distinct from ENDPOINT_TYPE_ATTRIBUTE so as seperate the inclusion of an attribute from its inclusion as a
+  reportable attribute. 
+  TODO integrate this into the ENDPOINT_TYPE_ATTRIBUTE table anyway?
+*/
+CREATE TABLE IF NOT EXISTS "ENDPOINT_TYPE_REPORTABLE_ATTRIBUTE" (
+  "ENDPOINT_TYPE_REF" integer, 
+  "ATTRIBUTE_REF" integer, 
+  "INCLUDED" integer,
+  "MIN_INTERVAL" integer, 
+  "MAX_INTERVAL" integer, 
+  "REPORTABLE_CHANGE" integer, 
+  foreign key (ENDPOINT_TYPE_REF) references ENDPOINT_TYPE(ENDPOINT_TYPE_ID) on delete cascade,
+  foreign key (ATTRIBUTE_REF) references ATTRIBUTE(ATTRIBUTE_ID)
+);
+
+
+
 /*
-  SETTING table contains site-specific application settings, regardless of a user configuration session.
-  Essentially application preferences.
+
+$$$$$$$$\        $$\                                                   
+\__$$  __|       \__|                                                  
+   $$ | $$$$$$\  $$\  $$$$$$\   $$$$$$\   $$$$$$\   $$$$$$\   $$$$$$$\ 
+   $$ |$$  __$$\ $$ |$$  __$$\ $$  __$$\ $$  __$$\ $$  __$$\ $$  _____|
+   $$ |$$ |  \__|$$ |$$ /  $$ |$$ /  $$ |$$$$$$$$ |$$ |  \__|\$$$$$$\  
+   $$ |$$ |      $$ |$$ |  $$ |$$ |  $$ |$$   ____|$$ |       \____$$\ 
+   $$ |$$ |      $$ |\$$$$$$$ |\$$$$$$$ |\$$$$$$$\ $$ |      $$$$$$$  |
+   \__|\__|      \__| \____$$ | \____$$ | \_______|\__|      \_______/ 
+                     $$\   $$ |$$\   $$ |                              
+                     \$$$$$$  |\$$$$$$  |                              
+                      \______/  \______/                               
+*/
+CREATE TRIGGER "INSERT_TRIGGER_ENDPOINT_TYPE_ATTRIBUTE" AFTER INSERT ON "ENDPOINT_TYPE_ATTRIBUTE"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = (SELECT SESSION_REF FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = NEW.ENDPOINT_TYPE_REF );
+END;
+CREATE TRIGGER "UPDATE_TRIGGER_ENDPOINT_TYPE_ATTRIBUTE" AFTER UPDATE ON "ENDPOINT_TYPE_ATTRIBUTE"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = (SELECT SESSION_REF FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = NEW.ENDPOINT_TYPE_REF );
+END;
+CREATE TRIGGER "DELETE_TRIGGER_ENDPOINT_TYPE_ATTRIBUTE" AFTER DELETE ON "ENDPOINT_TYPE_ATTRIBUTE"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = (SELECT SESSION_REF FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = OLD.ENDPOINT_TYPE_REF );
+END;
+
+
+CREATE TRIGGER "INSERT_TRIGGER_ENDPOINT_TYPE_COMMAND" AFTER INSERT ON "ENDPOINT_TYPE_COMMAND"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = (SELECT SESSION_REF FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = NEW.ENDPOINT_TYPE_REF );
+END;
+CREATE TRIGGER "UPDATE_TRIGGER_ENDPOINT_TYPE_COMMAND" AFTER UPDATE ON "ENDPOINT_TYPE_COMMAND"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = (SELECT SESSION_REF FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = NEW.ENDPOINT_TYPE_REF );
+END;
+CREATE TRIGGER "DELETE_TRIGGER_ENDPOINT_TYPE_COMMAND" AFTER DELETE ON "ENDPOINT_TYPE_COMMAND"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = (SELECT SESSION_REF FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = OLD.ENDPOINT_TYPE_REF );
+END;
+
+CREATE TRIGGER "INSERT_TRIGGER_ENDPOINT_TYPE_CLUSTER" AFTER INSERT ON "ENDPOINT_TYPE_CLUSTER"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = (SELECT SESSION_REF FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = NEW.ENDPOINT_TYPE_REF );
+END;
+CREATE TRIGGER "UPDATE_TRIGGER_ENDPOINT_TYPE_CLUSTER" AFTER UPDATE ON "ENDPOINT_TYPE_CLUSTER"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = (SELECT SESSION_REF FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = NEW.ENDPOINT_TYPE_REF );
+END;
+CREATE TRIGGER "DELETE_TRIGGER_ENDPOINT_TYPE_CLUSTER" AFTER DELETE ON "ENDPOINT_TYPE_CLUSTER"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = (SELECT SESSION_REF FROM ENDPOINT_TYPE WHERE ENDPOINT_TYPE_ID = OLD.ENDPOINT_TYPE_REF );
+END;
+
+CREATE TRIGGER "INSERT_TRIGGER_ENDPOINT_TYPE" AFTER INSERT ON "ENDPOINT_TYPE"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = NEW.SESSION_REF;
+END;
+CREATE TRIGGER "UPDATE_TRIGGER_ENDPOINT_TYPE" AFTER UPDATE ON "ENDPOINT_TYPE"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = NEW.SESSION_REF;
+END;
+CREATE TRIGGER "DELETE_TRIGGER_ENDPOINT_TYPE" AFTER DELETE ON "ENDPOINT_TYPE"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = OLD.SESSION_REF;
+END;
+
+CREATE TRIGGER "INSERT_TRIGGER_ENDPOINT" AFTER INSERT ON "ENDPOINT"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = NEW.SESSION_REF;
+END;
+CREATE TRIGGER "UPDATE_TRIGGER_ENDPOINT" AFTER UPDATE ON "ENDPOINT"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = NEW.SESSION_REF;
+END;
+CREATE TRIGGER "DELETE_TRIGGER_ENDPOINT" AFTER DELETE ON "ENDPOINT"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = OLD.SESSION_REF;
+END;
+
+CREATE TRIGGER "INSERT_TRIGGER_SESSION_KEY_VALUE" AFTER INSERT ON "SESSION_KEY_VALUE"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = NEW.SESSION_REF;
+END;
+CREATE TRIGGER "UPDATE_TRIGGER_SESSION_KEY_VALUE" AFTER UPDATE ON "SESSION_KEY_VALUE"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = NEW.SESSION_REF;
+END;
+CREATE TRIGGER "DELETE_TRIGGER_SESSION_KEY_VALUE" AFTER DELETE ON "SESSION_KEY_VALUE"
+BEGIN
+  UPDATE SESSION SET DIRTY = 1 WHERE SESSION_ID = OLD.SESSION_REF;
+END;
+
+
+
+/*
+
+ $$$$$$\  $$\           $$\                 $$\             $$\            $$\               
+$$  __$$\ $$ |          $$ |                $$ |            $$ |           $$ |              
+$$ /  \__|$$ | $$$$$$\  $$$$$$$\   $$$$$$\  $$ |       $$$$$$$ | $$$$$$\ $$$$$$\    $$$$$$\  
+$$ |$$$$\ $$ |$$  __$$\ $$  __$$\  \____$$\ $$ |      $$  __$$ | \____$$\\_$$  _|   \____$$\ 
+$$ |\_$$ |$$ |$$ /  $$ |$$ |  $$ | $$$$$$$ |$$ |      $$ /  $$ | $$$$$$$ | $$ |     $$$$$$$ |
+$$ |  $$ |$$ |$$ |  $$ |$$ |  $$ |$$  __$$ |$$ |      $$ |  $$ |$$  __$$ | $$ |$$\ $$  __$$ |
+\$$$$$$  |$$ |\$$$$$$  |$$$$$$$  |\$$$$$$$ |$$ |      \$$$$$$$ |\$$$$$$$ | \$$$$  |\$$$$$$$ |
+ \______/ \__| \______/ \_______/  \_______|\__|       \_______| \_______|  \____/  \_______|
+*/
+
+/*
+  Random settings, essentially application preferences
 */
 CREATE TABLE IF NOT EXISTS "SETTING" (
   "CATEGORY" text,
@@ -229,5 +453,10 @@ CREATE TABLE IF NOT EXISTS "SETTING" (
 );
 
 /*
-  Triggers to maintain "dirty" flag in a session.
- */
\ No newline at end of file
+  Previously touched file locations. This should be used as a history for dialogs.
+*/
+CREATE TABLE IF NOT EXISTS "FILE_LOCATION" (
+  "CATEGORY" text NOT NULL UNIQUE,
+  "FILE_PATH" path,
+  "ACCESS_TIME" integer
+);
\ No newline at end of file
diff --git a/src-electron/generator/static_generator.js b/src-electron/generator/static_generator.js
index db486cba..c9277299 100644
--- a/src-electron/generator/static_generator.js
+++ b/src-electron/generator/static_generator.js
@@ -6,7 +6,7 @@
 import Handlebars from 'handlebars';
 var fs = require('fs-extra');
 
-import { selectAllClusters, selectAllEnums, selectAllEnumItems, selectAllBitmaps, selectAllBitmapFields } from "../db/query.js"
+import { selectAllClusters, selectAllEnums, selectAllEnumItems, selectAllBitmaps, selectAllBitmapFields, selectAllStructs, selectAllStructItems } from "../db/query-zcl.js"
 
 /**
  * Find the handlebar template file, compile and return the template file.
@@ -107,6 +107,12 @@ export function infoFromDb(map, dbRowType) {
 			} else if (dbRowType[i] == "bitmaps") {
 				dbInfo[i] = selectAllBitmaps(db)
 				.then((dbRows) => map[dbRowType[i]] = dbRows);
+			} else if (dbRowType[i] === "print-cluster") {
+				dbInfo[i] = selectAllClusters(db)
+				.then((dbRows) => map[dbRowType[i]] = dbRows);
+			} else if (dbRowType[i] === "af-structs") {
+				dbInfo[i] = selectAllStructs(db)
+				.then((dbRows) => map[dbRowType[i]] = dbRows);
 			}
 		}
 		// Going through an array of promises and resolving them.
@@ -153,6 +159,8 @@ export function groupInfoIntoDbRow(map, groupByParams) {
 			subItems = selectAllEnumItems(db);
 		} else if (subItemName == 'BITMAP_FIELDS') {
 			subItems = selectAllBitmapFields(db);
+		} else if (subItemName == 'STRUCT_ITEMS') {
+			subItems = selectAllStructItems(db);
 		} else {
 			return;
 		}
diff --git a/src-electron/handlebars/helpers/helper_utils.js b/src-electron/handlebars/helpers/helper_utils.js
index 06921fdc..a404975d 100644
--- a/src-electron/handlebars/helpers/helper_utils.js
+++ b/src-electron/handlebars/helpers/helper_utils.js
@@ -9,6 +9,55 @@ export function getUppercase(str) {
 	return str.toUpperCase();
 };
 
+/**
+ *
+ *
+ * @export
+ * @param {*} value
+ * @param {*} options
+ * @returns String
+ * Description: getSwitch helper receives a options hash which contains
+ * options.fn that behaves like a compiled handlebars template.
+ */
+export function getSwitch(value, options) {
+	this.switch_value = value.toLowerCase();
+	this.switch_break = false;
+	return options.fn(this);
+};
+
+/**
+ *
+ *
+ * @export
+ * @param {*} value
+ * @param {*} options
+ * @returns String
+ * Description: getCase helper receives a options hash which contains
+ * options.fn that behaves like a compiled handlebars template.
+ */
+export function getCase(value, options) {
+	if (value == this.switch_value) {
+		this.switch_break = true;
+	  	return options.fn(this);
+	}
+};
+
+/**
+ *
+ *
+ * @export
+ * @param {*} value
+ * @param {*} options
+ * @returns String
+ * Description: getDefault helper receives a options hash which contains
+ * options.fn that behaves like a compiled handlebars template.
+ */
+export function getDefault(value, options) {
+	if (this.switch_break == false) {
+		return options.fn(this);
+	}
+ };
+
 /**
 Given: String
 Return: String
@@ -52,4 +101,22 @@ function findAndReplace(string, target, replacement) {
 		}
 	}
 	return string;
+}
+
+/**
+ *
+ *
+ * Given: String Array
+ * @returns the length of largest String in the array
+ */
+export function getLargestStringInArray() {
+	var stringArray = arguments[0];
+	var lengthOfLargestString = 0, i = 0, stringLength = 0;
+	for(i=0; i<stringArray.length;i++) {
+		stringLength = stringArray[i].NAME.length;
+		if ( stringLength > lengthOfLargestString ) {
+			lengthOfLargestString = stringLength;
+		}
+	}
+	return lengthOfLargestString;
 }
\ No newline at end of file
diff --git a/src-electron/main-process/args.js b/src-electron/main-process/args.js
index 14a55420..070b3db6 100644
--- a/src-electron/main-process/args.js
+++ b/src-electron/main-process/args.js
@@ -27,7 +27,7 @@ export function processCommandLineArguments(argv) {
           })
       })
     .command(
-      'selfcheck',
+      'selfCheck',
       'Perform the self-check of the application.'
     )
     .option('httpPort', {
@@ -45,6 +45,9 @@ export function processCommandLineArguments(argv) {
     .option('noUi', {
       desc: 'Don\'t show the main window when starting.'
     })
+    .option('showUrl', {
+      desc: 'Print out the URL that an external browser should use.'
+    })
     .usage('Usage: $0 <command> [options]')
     .help()
     .parse(argv)
diff --git a/src-electron/main-process/electron-main.js b/src-electron/main-process/electron-main.js
index 6205e069..4b14ff4e 100644
--- a/src-electron/main-process/electron-main.js
+++ b/src-electron/main-process/electron-main.js
@@ -39,7 +39,7 @@ function startSelfCheck() {
     })
 }
 
-function startNormal(ui) {
+function startNormal(ui, showUrl) {
   initDatabase(sqliteFile())
     .then((db) => attachToDb(db))
     .then((db) => loadSchema(db, schemaFile(), version))
@@ -49,8 +49,12 @@ function startNormal(ui) {
       if (ui) {
         initializeElectronUi(httpPort)
       } else {
-        if (app.dock)
+        if (app.dock) {
           app.dock.hide()
+        }
+        if ( showUrl ) {
+          console.log(`http://localhost:${httpPort}/index.html`)
+        }
       }
     })
     .catch((err) => {
@@ -62,10 +66,12 @@ function startNormal(ui) {
 app.on('ready', () => {
   var argv = processCommandLineArguments(process.argv)
 
-  if ( argv._.includes('selfcheck')) {
+  logInfo(argv)
+  
+  if ( argv._.includes('selfCheck')) {
     startSelfCheck()
   } else {
-    startNormal(!argv.noUi)
+    startNormal(!argv.noUi, argv.showUrl)
   }
 })
 
diff --git a/src-electron/main-process/importexport.js b/src-electron/main-process/importexport.js
index 29a61e0b..ae4bfc56 100644
--- a/src-electron/main-process/importexport.js
+++ b/src-electron/main-process/importexport.js
@@ -1,18 +1,88 @@
-/*
- * Created Date: Tuesday, March 10th 2020, 4:19:32 pm
- * Author: Timotej Ecimovic
- * 
- * Copyright (c) 2020 Silicon Labs
- * 
+// Copyright (c) 2020 Silicon Labs. All rights reserved.
+
+/* 
  * This file provides functionality provides file operations for zap, namely the export
  * from the database and the import into the database.
  */
-
 import fs from 'fs'
-import { getAllSesionKeyValues, getAllSessionClusterState, getAllEndpointTypes } from '../db/query'
 import { logInfo } from './env'
+import { getAllSesionKeyValues, getAllEndpointTypes } from '../db/query-config'
+import { setSessionClean } from '../db/query-session'
+
+///////////////////////////////// IMPORT ////////////////////////////////////
+
+/**
+ * Take a given session ID and import the data from the file
+ *
+ * @export
+ * @param {*} sessionId
+ * @param {*} filePath
+ * @returns a promise that resolves with the resolution of writing into a database.
+ */
+export function importDataFromFile(sessionId, filePath) {
+    return new Promise((resolve, reject) => {
+        fs.readFile(filePath, (err, data) => {
+            if (err) reject(err)
+            let state = JSON.parse(data)
+            resolve(state)
+        })
+    }).then(state => writeStateToDatabase(sessionId, state))
+}
+
+/**
+ * Given a state object, this method returns a promise that resolves
+ * with the succesfull writing into the database.
+ *
+ * @export
+ * @param {*} sessionId
+ * @param {*} state
+ * @returns a promise that resolves with the sucessful writing
+ */
+export function writeStateToDatabase(sessionId, state) {
+    return new Promise((resolve,reject) => {
+        logInfo('Reading state from file into the database...')
+        logInfo(state)
+        resolve()
+    })
+}
+
+///////////////////////////////// EXPORT ////////////////////////////////////
+
+/**
+ * Toplevel file that takes a given session ID and exports the data into the file
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @param {*} filePath
+ * @returns A promise that resolves with the path of the file written.
+ */
+export function exportDataIntoFile(db, sessionId, filePath) {
+    return createStateFromDatabase(db, sessionId)
+        .then(state => {
+            return new Promise((resolve, reject) => {
+                fs.writeFile(filePath, JSON.stringify(state, null, 2), (err) => {
+                    if (err) reject(err)
+                    resolve()
+                })
+            })
+        }).then(() => {
+            return setSessionClean(db, sessionId)
+        }).then(() => {
+            return Promise.resolve(filePath)
+        })
+}
 
-function createStateFromDatabase(db, sessionId) {
+/**
+ * Given a database and a session id, this method returns a promise that
+ * resolves with a state object that needs to be saved into a file.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @returns state object that needs to be saved into a file.
+ */
+export function createStateFromDatabase(db, sessionId) {
     return new Promise((resolve, reject) => {
         var state = {
             writeTime: (new Date()).toString(),
@@ -24,47 +94,23 @@ function createStateFromDatabase(db, sessionId) {
         var getKeyValues = getAllSesionKeyValues(db, sessionId)
             .then(rows => {
                 state.keyValuePairs = rows
+                logInfo('Retrieved session keys')
                 return Promise.resolve(rows)
             })
+        promises.push(getKeyValues)
 
         var getAllEndpoint = getAllEndpointTypes(db, sessionId)
            .then(rows => {
-               state.endpointTypes = rows
+            logInfo('Retrieved endpoint types')
+            state.endpointTypes = rows
                return Promise.resolve(rows)
            })
-        promises.push(getKeyValues)
+        promises.push(getAllEndpoint)
 
+        
         Promise.all(promises)
             .then(() => resolve(state))
+            .catch(err => reject(err))
     })
 }
 
-function writeStateToDatabase(sessionId, state) {
-    return new Promise((resolve,reject) => {
-        resolve()
-    })
-}
-
-// Take a given session ID and export the data into the file
-export function exportDataIntoFile(db, sessionId, filePath) {
-    return createStateFromDatabase(db, sessionId)
-        .then(state => {
-            return new Promise((resolve, reject) => {
-                fs.writeFile(filePath, JSON.stringify(state, null, 2), (err) => {
-                    if (err) reject(err)
-                    resolve(filePath)
-                })
-            })
-        })
-}
-
-// Take a given session ID and import the data from the file
-export function importDataFromFile(sessionId, filePath) {
-    return new Promise((resolve, reject) => {
-        fs.readFile(filePath, (err, data) => {
-            if (err) reject(err)
-            let state = JSON.parse(data)
-            resolve(state)
-        })
-    }).then(state => writeStateToDatabase(sessionId, state))
-}
\ No newline at end of file
diff --git a/src-electron/main-process/menu.js b/src-electron/main-process/menu.js
index e086ebe9..b62ad723 100644
--- a/src-electron/main-process/menu.js
+++ b/src-electron/main-process/menu.js
@@ -1,13 +1,14 @@
 // Copyright (c) 2019 Silicon Labs. All rights reserved.
 
-import { Menu, dialog } from 'electron'
-import { windowCreate } from './window.js'
-import { mainDatabase, logError, logInfo, appDirectory } from './env.js'
-import { mapDatabase, resolveTemplateDirectory, compileTemplate, infoFromDb, generateDataToFile, groupInfoIntoDbRow, resolveHelper } from '../generator/static_generator.js'
-import { getUppercase, getStrong, getHexValue } from "../handlebars/helpers/helper_utils.js"
-import { getSessionIdFromWindowdId } from '../db/query.js'
+import { dialog, Menu } from 'electron'
+import { getSessionIdFromWindowdId } from '../db/query-session.js'
+import { compileTemplate, generateDataToFile, groupInfoIntoDbRow, infoFromDb, mapDatabase, resolveHelper, resolveTemplateDirectory } from '../generator/static_generator.js'
+import { getHexValue, getStrong, getUppercase, getLargestStringInArray, getSwitch, getCase, getDefault } from "../handlebars/helpers/helper_utils.js"
+import { appDirectory, logError, logInfo, mainDatabase } from './env.js'
 import { exportDataIntoFile } from './importexport.js'
 import { showErrorMessage } from './ui.js'
+import { windowCreate } from './window.js'
+import { selectFileLocation, insertFileLocation } from '../db/query-generic.js'
 
 var httpPort
 var generationDirectory = appDirectory() + "/generation-output"
@@ -19,19 +20,19 @@ const template = [
     submenu: [
       {
         label: 'Generate Code',
-        click (menuItem, browserWindow, event) {
+        click(menuItem, browserWindow, event) {
           generateInDir(browserWindow)
         }
       },
       {
         label: 'Handlebar Template Directory',
-        click (menuItem, browserWindow, event) {
+        click(menuItem, browserWindow, event) {
           setHandlebarTemplateDirectory(browserWindow)
         }
       },
       {
         label: 'Open File...',
-        click (menuItem, browserWindow, event) {
+        click(menuItem, browserWindow, event) {
           doOpen(menuItem, browserWindow, event)
         }
       },
@@ -40,23 +41,26 @@ const template = [
       },
       {
         label: 'Session Information...',
-        click (menuItem, browserWindow, event) {
+        click(menuItem, browserWindow, event) {
           let winId = browserWindow.id
           getSessionIdFromWindowdId(mainDatabase(), winId).then(row => {
             dialog.showMessageBox(browserWindow, {
               title: 'Information',
               message: `Window id: ${winId}\nZap session id: ${row.sessionId}\nSession key: ${row.sessionKey}\nTime: ${new Date(row.creationTime)}`,
-              buttons: [ 'Dismiss' ]
-            })  
+              buttons: ['Dismiss']
+            })
           }).catch(err => showErrorMessage('Session info', err))
         }
       },
       {
-        label: 'Save'
+        label: 'Save',
+        click(menuItem, browserWindow, event) {
+          doSave(menuItem, browserWindow, event)
+        }
       },
       {
         label: 'Save As...',
-        click (menuItem, browserWindow, event) {
+        click(menuItem, browserWindow, event) {
           doSaveAs(menuItem, browserWindow, event)
         }
       },
@@ -92,113 +96,166 @@ const template = [
     ]
   }
 ]
-
+/**
+ * Perform a file->open operation.
+ *
+ * @param {*} menuItem
+ * @param {*} browserWindow
+ * @param {*} event
+ */
 function doOpen(menuItem, browserWindow, event) {
-  dialog.showOpenDialog({
-    properties: ['multiSelections']
-  }).then(result => {
-    if (!result.canceled) {
-      fileOpen(mainDatabase(), browserWindow.id, result.filePaths)
-    }
-  }).catch(err => showErrorMessage('Open file', err))
+  selectFileLocation(mainDatabase(), 'save')
+    .then(filePath => {
+      var opts = {
+        properties: ['multiSelections']
+      }
+      if (filePath != null) {
+        opts.defaultPath = filePath
+      }
+      return dialog.showOpenDialog(opts)
+    })
+    .then(result => {
+      if (!result.canceled) {
+        fileOpen(mainDatabase(), browserWindow.id, result.filePaths)
+      }
+    }).catch(err => showErrorMessage('Open file', err))
 }
 
+/**
+ * Perform a save, defering to save as if file is not yet selected.
+ *
+ * @param {*} menuItem
+ * @param {*} browserWindow
+ * @param {*} event
+ */
+function doSave(menuItem, browserWindow, event) {
+  doSaveAs(menuItem, browserWindow, event)
+}
+
+/**
+ * Perform save as.
+ *
+ * @param {*} menuItem
+ * @param {*} browserWindow
+ * @param {*} event
+ */
 function doSaveAs(menuItem, browserWindow, event) {
-  dialog.showSaveDialog({}).then(result => {
-    if(!result.canceled) {
-      return fileSave(mainDatabase(), browserWindow.id, result.filePath)
-    } else {
-      return Promise.resolve(null)
-    }
-  }).then(filePath => {
-    if ( filePath != null ) {
-      dialog.showMessageBox(browserWindow, {
-        title: 'Save',
-        message: `Save done. Output: ${filePath}`,
-        buttons: [ 'Ok' ]
-      })
-    }
-  })
-  .catch(err => showErrorMessage('Save file', err))
+  selectFileLocation(mainDatabase(), 'save')
+    .then(
+      filePath => {
+        var opts = {}
+        if (filePath != null) {
+          opts.defaultPath = filePath
+        }
+        return dialog.showSaveDialog(opts)
+      }
+    )
+    .then(result => {
+      if (!result.canceled) {
+        return fileSave(mainDatabase(), browserWindow.id, result.filePath)
+      } else {
+        return Promise.resolve(null)
+      }
+    })
+    .then(filePath => {
+      if (filePath != null) {
+        insertFileLocation(mainDatabase(), filePath, 'save')
+        dialog.showMessageBox(browserWindow, {
+          title: 'Save',
+          message: `Save done. Output: ${filePath}`,
+          buttons: ['Ok']
+        })
+      }
+    })
+    .catch(err => showErrorMessage('Save file', err))
 }
 
 /**
-Given: Browser Window
-Returns: N/A
-Description: This function gets the directory where user wants the output and
-calls generateCode function which generates the code in the user selected
-output.
-*/
+ * This function gets the directory where user wants the output and
+ * calls generateCode function which generates the code in the user selected
+ * output.
+ *
+ * @param {*} browserWindow
+ */
 function generateInDir(browserWindow) {
-  dialog.showOpenDialog({properties: ['openDirectory']}).then(result => {
-    if(!result.canceled) {
+  dialog.showOpenDialog({ properties: ['openDirectory'] }).then(result => {
+    if (!result.canceled) {
       return Promise.resolve(result.filePaths[0])
     } else {
       return Promise.resolve(null)
     }
   }).then(filePath => {
-    if ( filePath != null ) {
+    if (filePath != null) {
       generationDirectory = filePath
       generateCode(mainDatabase())
       dialog.showMessageBox(browserWindow, {
         title: 'Generation',
         message: `Generation Output: ${filePath}`,
-        buttons: [ 'Ok' ]
+        buttons: ['Ok']
       })
     }
   })
-  .catch(err => showErrorMessage('Save file', err))
+    .catch(err => showErrorMessage('Save file', err))
 }
 
 /**
-Given: Browser Window
-Returns: N/A
-Description: This function gets the directory where user wants the output and
-calls generateCode function which generates the code in the user selected
-output.
-*/
+ * This function gets the directory where user wants the output and calls 
+ * generateCode function which generates the code in the user selected output.
+ *
+ * @param {*} browserWindow
+ */
 function setHandlebarTemplateDirectory(browserWindow) {
-  dialog.showOpenDialog({properties: ['openDirectory']}).then(result => {
-    if(!result.canceled) {
+  dialog.showOpenDialog({ properties: ['openDirectory'] }).then(result => {
+    if (!result.canceled) {
       return Promise.resolve(result.filePaths[0])
     } else {
       return Promise.resolve(null)
     }
   }).then(filePath => {
-    if ( filePath != null ) {
+    if (filePath != null) {
       handlebarTemplateDirectory = filePath
       dialog.showMessageBox(browserWindow, {
         title: 'Handlebar Templates',
         message: `Handlebar Template Directory: ${filePath}`,
-        buttons: [ 'Ok' ]
+        buttons: ['Ok']
       })
     }
   })
-  .catch(err => showErrorMessage('Save file', err))
+    .catch(err => showErrorMessage('Save file', err))
 }
 
 /**
-Given: N/A
-Returns: N/A
-Description: This function generates the code into the user defined directory using promises
-*/
-function generateCode (db) {
-  const HANDLEBAR_HELPER_UPPERCASE =  'uppercase';
-  const HANDLEBAR_HELPER_STRONG =  'strong';
-  const HANDLEBAR_HELPER_HEX_VALUE =  'hexValue';
-  const HANDLEBAR_TEMPLATE_FILE_CLUSTERS = "cluster-id.handlebars"
-  const HANDLEBAR_TEMPLATE_FILE_ENUMS = "enums.handlebars"
-  const HANDLEBAR_TEMPLATE_FILE_BITMAPS = "bitmaps.handlebars"
-  const DATABASE_ROW_TYPE_CLUSTER = "clusters"
-  const DATABASE_ROW_TYPE_ENUMS = "enums"
-  const DATABASE_ROW_TYPE_BITMAPS = "bitmaps"
+ * This function generates the code into the user defined directory using promises
+ *
+ * @param {*} db
+ */
+function generateCode(db) {
+  const HANDLEBAR_HELPER_UPPERCASE = 'uppercase';
+  const HANDLEBAR_HELPER_STRONG = 'strong';
+  const HANDLEBAR_HELPER_HEX_VALUE = 'hexValue';
+  const HANDLEBAR_HELPER_LENGTH_OF_LARGEST_STRING = 'largestStringInArray';
+  const HANDLEBAR_HELPER_SWITCH = "switch";
+  const HANDLEBAR_HELPER_CASE = "case";
+  const HANDLEBAR_HELPER_DEFAULT = "default";
+  const HANDLEBAR_TEMPLATE_FILE_ATT_STORAGE = "att-storage.handlebars";
+  const HANDLEBAR_TEMPLATE_FILE_AF_STRUCTS = "af-structs.handlebars";
+  const HANDLEBAR_TEMPLATE_FILE_CLUSTERS = "cluster-id.handlebars";
+  const HANDLEBAR_TEMPLATE_FILE_ENUMS = "enums.handlebars";
+  const HANDLEBAR_TEMPLATE_FILE_BITMAPS = "bitmaps.handlebars";
+  const HANDLEBAR_TEMPLATE_FILE_PRINT_CLUSTERS = "print-cluster.handlebars";
+  const DATABASE_ROW_TYPE_CLUSTER = "clusters";
+  const DATABASE_ROW_TYPE_ENUMS = "enums";
+  const DATABASE_ROW_TYPE_BITMAPS = "bitmaps";
+  const DATABASE_ROW_TYPE_AF_STRUCTS = "af-structs";
+  const DATABASE_ROW_TYPE_PRINT_CLUSTER = "print-cluster";
+  const DATABASE_ROW_TYPE_ATT_STORAGE = "att-storage";
 
   //cluster-id.h generation
   var clusterHandleBarHelpers = {}
   clusterHandleBarHelpers[HANDLEBAR_HELPER_UPPERCASE] = getUppercase;
-  var clusterRowToHandlebarTemplateFileMap = [{dbRowType: DATABASE_ROW_TYPE_CLUSTER, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_CLUSTERS}];
-    mapDatabase(db)
-    .then(templateDir =>resolveTemplateDirectory(templateDir, handlebarTemplateDirectory))
+  var clusterRowToHandlebarTemplateFileMap = [{ dbRowType: DATABASE_ROW_TYPE_CLUSTER, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_CLUSTERS }];
+  mapDatabase(db)
+    .then(templateDir => resolveTemplateDirectory(templateDir, handlebarTemplateDirectory))
     .then(templates => compileTemplate(templates, [HANDLEBAR_TEMPLATE_FILE_CLUSTERS]))
     .then(databaseRows => infoFromDb(databaseRows, [DATABASE_ROW_TYPE_CLUSTER]))
     .then(helperResolution => resolveHelper(helperResolution, clusterHandleBarHelpers))
@@ -210,28 +267,81 @@ function generateCode (db) {
   var enumHandleBarHelpers = {}
   enumHandleBarHelpers[HANDLEBAR_HELPER_STRONG] = getStrong;
   enumHandleBarHelpers[HANDLEBAR_HELPER_HEX_VALUE] = getHexValue;
-  var enumsRowToHandlebarTemplateFileMap = [{dbRowType: DATABASE_ROW_TYPE_ENUMS, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_ENUMS},
-                                            {dbRowType: DATABASE_ROW_TYPE_BITMAPS, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_BITMAPS}];
+  var enumsRowToHandlebarTemplateFileMap = [{ dbRowType: DATABASE_ROW_TYPE_ENUMS, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_ENUMS },
+  { dbRowType: DATABASE_ROW_TYPE_BITMAPS, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_BITMAPS }];
   mapDatabase(db)
-    .then(templateDir =>resolveTemplateDirectory(templateDir, handlebarTemplateDirectory))
+    .then(templateDir => resolveTemplateDirectory(templateDir, handlebarTemplateDirectory))
     .then(templates => compileTemplate(templates, [HANDLEBAR_TEMPLATE_FILE_ENUMS, HANDLEBAR_TEMPLATE_FILE_BITMAPS]))
     .then(databaseRows => infoFromDb(databaseRows, [DATABASE_ROW_TYPE_ENUMS, DATABASE_ROW_TYPE_BITMAPS]))
-    .then(databaseRowsWithEnumItems => groupInfoIntoDbRow(databaseRowsWithEnumItems, {tableName: 'ENUM_ITEMS', foreignKey: 'ENUM_REF', primaryKey: 'ENUM_ID', dbType: 'enums', columns: {NAME: "NAME", VALUE: "VALUE"}} ))
-    .then(databaseRowsWithBitmapFields => groupInfoIntoDbRow(databaseRowsWithBitmapFields, {tableName: 'BITMAP_FIELDS', foreignKey: 'BITMAP_REF', primaryKey: 'BITMAP_ID', dbType: 'bitmaps', columns: {NAME: "NAME", VALUE: "MASK"}}))
+    .then(databaseRowsWithEnumItems => groupInfoIntoDbRow(databaseRowsWithEnumItems, { tableName: 'ENUM_ITEMS', foreignKey: 'ENUM_REF', primaryKey: 'ENUM_ID', dbType: 'enums', columns: { NAME: "NAME", VALUE: "VALUE" } }))
+    .then(databaseRowsWithBitmapFields => groupInfoIntoDbRow(databaseRowsWithBitmapFields, { tableName: 'BITMAP_FIELDS', foreignKey: 'BITMAP_REF', primaryKey: 'BITMAP_ID', dbType: 'bitmaps', columns: { NAME: "NAME", VALUE: "MASK" } }))
     .then(helperResolution => resolveHelper(helperResolution, enumHandleBarHelpers))
     .then(directoryResolution => resolveGenerationDirectory(directoryResolution))
     .then(resultToFile => generateDataToFile(resultToFile, 'enums.h', enumsRowToHandlebarTemplateFileMap))
-    .catch(err => logError(err))  
-}
+    .catch(err => logError(err))
+
+  //print-cluster.h
+  var printClusterHandleBarHelpers = {}
+  printClusterHandleBarHelpers[HANDLEBAR_HELPER_UPPERCASE] = getUppercase;
+  printClusterHandleBarHelpers[HANDLEBAR_HELPER_LENGTH_OF_LARGEST_STRING] = getLargestStringInArray;
+  var printClusterRowToHandleBarTemplateFileMap = [{ dbRowType: DATABASE_ROW_TYPE_PRINT_CLUSTER, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_PRINT_CLUSTERS }];
+  mapDatabase(db)
+    .then(templateDir => resolveTemplateDirectory(templateDir, handlebarTemplateDirectory))
+    .then(templates => compileTemplate(templates, [HANDLEBAR_TEMPLATE_FILE_PRINT_CLUSTERS]))
+    .then(databaseRows => infoFromDb(databaseRows, [DATABASE_ROW_TYPE_PRINT_CLUSTER]))
+    .then(helperResolution => resolveHelper(helperResolution, printClusterHandleBarHelpers))
+    .then(directoryResolution => resolveGenerationDirectory(directoryResolution))
+    .then(resultToFile => generateDataToFile(resultToFile, 'print-cluster.h', printClusterRowToHandleBarTemplateFileMap))
+    .catch(err => logError(err))
+
+  //af-structs.h
+  var afStructsHandleBarHelpers = {}
+  afStructsHandleBarHelpers[HANDLEBAR_HELPER_SWITCH] = getSwitch;
+  afStructsHandleBarHelpers[HANDLEBAR_HELPER_CASE] = getCase;
+  afStructsHandleBarHelpers[HANDLEBAR_HELPER_DEFAULT] = getDefault;
+  var afStructsRowToHandleBarTemplateFileMap = [{ dbRowType: DATABASE_ROW_TYPE_AF_STRUCTS, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_AF_STRUCTS }];
+  mapDatabase(db)
+    .then(templateDir => resolveTemplateDirectory(templateDir, handlebarTemplateDirectory))
+    .then(templates => compileTemplate(templates, [HANDLEBAR_TEMPLATE_FILE_AF_STRUCTS]))
+    .then(databaseRows => infoFromDb(databaseRows, [DATABASE_ROW_TYPE_AF_STRUCTS]))
+    .then(databaseRowsWithEnumItems => groupInfoIntoDbRow(databaseRowsWithEnumItems, { tableName: 'STRUCT_ITEMS', foreignKey: 'STRUCT_REF', primaryKey: 'STRUCT_ID', dbType: 'af-structs', columns: { NAME: "NAME", VALUE: "TYPE" } }))
+    .then(helperResolution => resolveHelper(helperResolution, afStructsHandleBarHelpers))
+    .then(directoryResolution => resolveGenerationDirectory(directoryResolution))
+    .then(resultToFile => generateDataToFile(resultToFile, 'af-structs.h', afStructsRowToHandleBarTemplateFileMap))
+    .catch(err => logError(err))
+    
+  //att-storage.h generation
+  var attStorageRowToHandleBarTemplateFileMap = [{ dbRowType: DATABASE_ROW_TYPE_ATT_STORAGE, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_ATT_STORAGE }];
 
-// This function is called when file save is triggered.
-function fileSave (db, winId, filePath) {
+  mapDatabase(db)
+      .then(templateDir => resolveTemplateDirectory(templateDir, ""))
+      .then(templates => compileTemplate(templates, [HANDLEBAR_TEMPLATE_FILE_ATT_STORAGE]))
+      .then(directoryResolution => resolveGenerationDirectory(directoryResolution))
+      .then(resultToFile => generateDataToFile(resultToFile, 'att-storage.h', attStorageRowToHandleBarTemplateFileMap))
+      .catch(err => logError(err))
+}
+/**
+ * perform the save.
+ *
+ * @param {*} db
+ * @param {*} winId
+ * @param {*} filePath
+ * @returns Promise of saving.
+ */
+function fileSave(db, winId, filePath) {
   return getSessionIdFromWindowdId(db, winId)
-    .then(row => exportDataIntoFile(db, row.sessionId, filePath));
+    .then(row => exportDataIntoFile(db, row.sessionId, filePath))
+    .catch(err => showErrorMessage("File save", err))
 }
 
-// This function is called when file open is triggered.
-function fileOpen (db, winId, filePaths) {
+/**
+ * Perform the do open action.
+ *
+ * @param {*} db
+ * @param {*} winId
+ * @param {*} filePaths
+ */
+function fileOpen(db, winId, filePaths) {
   filePaths.forEach((item, index) => {
     logInfo(`Opening: ${item}`)
     windowCreate(httpPort, item)
@@ -239,19 +349,26 @@ function fileOpen (db, winId, filePaths) {
 }
 
 /**
-Given: a map and a generation directory path.
-Return: a map which has the generation directory.
-Description: Resolve the generation directory to be able to generate to the
-correct directory.
-*/
+ * Description: Resolve the generation directory to be able to generate to the
+ * correct directory.
+ * @export
+ * @param {*} map
+ * @returns promise that resolves into a map.
+ */
 export function resolveGenerationDirectory(map) {
-	return new Promise((resolve, reject) => {
-		map.generationDirectory = generationDirectory;
-		resolve(map);
-	})
+  return new Promise((resolve, reject) => {
+    map.generationDirectory = generationDirectory;
+    resolve(map);
+  })
 }
 
-export function initMenu (port) {
+/**
+ * Initialize a menu.
+ *
+ * @export
+ * @param {*} port
+ */
+export function initMenu(port) {
   httpPort = port
   const menu = Menu.buildFromTemplate(template)
   Menu.setApplicationMenu(menu)
diff --git a/src-electron/main-process/window.js b/src-electron/main-process/window.js
index c231ec3c..30ff2f71 100644
--- a/src-electron/main-process/window.js
+++ b/src-electron/main-process/window.js
@@ -1,10 +1,12 @@
 // Copyright (c) 2019 Silicon Labs. All rights reserved.
 
-import { logInfo, iconsDirectory } from './env.js'
+import { logInfo, iconsDirectory, mainDatabase, logError } from './env.js'
 import { initMenu } from './menu.js'
 import { initTray } from './tray.js'
-import { session, BrowserWindow } from 'electron'
+import { session, BrowserWindow, dialog } from 'electron'
 import path from 'path'
+import { getSessionDirtyFlag, getSessionIdFromWindowdId, getWindowDirtyFlagWithCallback } from '../db/query-session.js'
+import { showErrorMessage } from './ui.js'
 
 export function initializeElectronUi(port) {
   let w = windowCreate(port)
@@ -12,7 +14,7 @@ export function initializeElectronUi(port) {
   initTray(port)
 }
 
-export function windowCreateIfNotThere (port) {
+export function windowCreateIfNotThere(port) {
   if (BrowserWindow.getAllWindows().length == 0) {
     windowCreate(port)
   }
@@ -21,25 +23,49 @@ export function windowCreateIfNotThere (port) {
 let windowCounter = 0
 
 // Create a new window from a given path.
-export function windowCreate (port, filePath = null) {
+export function windowCreate(port, filePath = null) {
   logInfo(__dirname)
   let newSession = session.fromPartition(`zap-${windowCounter++}`)
   let w = new BrowserWindow({
-      width: 1600,
-      height: 800,
-      resizable: true,
-      center: true,
-      icon: path.join(iconsDirectory(), 'zap_32x32.png'),
-      title: filePath == null ? 'New Configuration' : filePath,
-      useContentSize: true,
-      webPreferences: {
-        nodeIntegration: false,
-        session: newSession
-      }
-    })
+    width: 1600,
+    height: 800,
+    resizable: true,
+    center: true,
+    icon: path.join(iconsDirectory(), 'zap_32x32.png'),
+    title: filePath == null ? 'New Configuration' : filePath,
+    useContentSize: true,
+    webPreferences: {
+      nodeIntegration: false,
+      session: newSession
+    }
+  })
   w.loadURL(`http://localhost:${port}/index.html?winId=${w.id}`)
   w.on('page-title-updated', (e) => {
     e.preventDefault()
-  })
+  }) // EO page-title-updated
+
+  w.on('close', (e) => {
+    e.preventDefault()
+    getWindowDirtyFlagWithCallback(mainDatabase(), w.id, (dirty) => {
+      if ( dirty ) {
+        const result = dialog.showMessageBoxSync(w, {
+          type: 'warning',
+          title: 'Unsaved changes?',
+          message: 'Your changes will be lost if you do not save them into the file.',
+          buttons: [
+            'Quit Anyway',
+            'Cancel',
+          ],
+          defaultId: 0,
+          cancelId: 1
+        });
+  
+        if (result === 0) w.destroy(); 
+      } else {
+        w.destroy()
+      }
+    })
+  }) // EO close
+
   return w
 }
diff --git a/src-electron/rest/generation.js b/src-electron/rest/generation.js
index 7d1c61ae..d2abb839 100644
--- a/src-electron/rest/generation.js
+++ b/src-electron/rest/generation.js
@@ -8,7 +8,7 @@
 
 import { logError } from '../main-process/env';
 import { mapDatabase, resolveTemplateDirectory, compileTemplate, infoFromDb, groupInfoIntoDbRow, resolveHelper, generateDataToPreview } from '../generator/static_generator.js'
-import { getUppercase, getStrong, getHexValue } from "../handlebars/helpers/helper_utils.js"
+import { getUppercase, getStrong, getHexValue, getLargestStringInArray, getSwitch, getCase, getDefault } from "../handlebars/helpers/helper_utils.js"
 
 /**
  *
@@ -23,12 +23,22 @@ export function registerGenerationApi(db, app) {
         const HANDLEBAR_HELPER_UPPERCASE = 'uppercase';
         const HANDLEBAR_HELPER_STRONG = 'strong';
         const HANDLEBAR_HELPER_HEX_VALUE = 'hexValue';
-        const HANDLEBAR_TEMPLATE_FILE_CLUSTERS = "cluster-id.handlebars"
-        const HANDLEBAR_TEMPLATE_FILE_ENUMS = "enums.handlebars"
-        const HANDLEBAR_TEMPLATE_FILE_BITMAPS = "bitmaps.handlebars"
-        const DATABASE_ROW_TYPE_CLUSTER = "clusters"
-        const DATABASE_ROW_TYPE_ENUMS = "enums"
-        const DATABASE_ROW_TYPE_BITMAPS = "bitmaps"
+        const HANDLEBAR_HELPER_LENGTH_OF_LARGEST_STRING = 'largestStringInArray';
+        const HANDLEBAR_HELPER_SWITCH = "switch";
+        const HANDLEBAR_HELPER_CASE = "case";
+        const HANDLEBAR_HELPER_DEFAULT = "default";
+        const HANDLEBAR_TEMPLATE_FILE_ATT_STORAGE = "att-storage.handlebars";
+        const HANDLEBAR_TEMPLATE_FILE_AF_STRUCTS = "af-structs.handlebars";
+        const HANDLEBAR_TEMPLATE_FILE_CLUSTERS = "cluster-id.handlebars";
+        const HANDLEBAR_TEMPLATE_FILE_ENUMS = "enums.handlebars";
+        const HANDLEBAR_TEMPLATE_FILE_BITMAPS = "bitmaps.handlebars";
+        const HANDLEBAR_TEMPLATE_FILE_PRINT_CLUSTERS = "print-cluster.handlebars";
+        const DATABASE_ROW_TYPE_CLUSTER = "clusters";
+        const DATABASE_ROW_TYPE_ENUMS = "enums";
+        const DATABASE_ROW_TYPE_BITMAPS = "bitmaps";
+        const DATABASE_ROW_TYPE_PRINT_CLUSTER = "print-cluster";
+        const DATABASE_ROW_TYPE_AF_STRUCTS = "af-structs";
+        const DATABASE_ROW_TYPE_ATT_STORAGE = "att-storage";
 
 
         //cluster-id.h generation
@@ -61,10 +71,55 @@ export function registerGenerationApi(db, app) {
             .then(resultToFile => generateDataToPreview(resultToFile, enumsRowToHandlebarTemplateFileMap))
             .catch(err => logError(err))
 
+        //print-cluster.h generation
+        var printClusterHandleBarHelpers = {}
+        printClusterHandleBarHelpers[HANDLEBAR_HELPER_UPPERCASE] = getUppercase;
+        printClusterHandleBarHelpers[HANDLEBAR_HELPER_LENGTH_OF_LARGEST_STRING] = getLargestStringInArray;
+        var printClusterRowToHandleBarTemplateFileMap = [{ dbRowType: DATABASE_ROW_TYPE_PRINT_CLUSTER, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_PRINT_CLUSTERS }];
+
+        const printClusterGenerationCode = await mapDatabase(db)
+            .then(templateDir => resolveTemplateDirectory(templateDir, ""))
+            .then(templates => compileTemplate(templates, [HANDLEBAR_TEMPLATE_FILE_PRINT_CLUSTERS]))
+            .then(databaseRows => infoFromDb(databaseRows, [DATABASE_ROW_TYPE_PRINT_CLUSTER]))
+            .then(helperResolution => resolveHelper(helperResolution, printClusterHandleBarHelpers))
+            .then(resultToFile => generateDataToPreview(resultToFile, printClusterRowToHandleBarTemplateFileMap))
+            .catch(err => logError(err))
+
+        //af-structs.h generation
+        var afStructsHandleBarHelpers = {}
+        afStructsHandleBarHelpers[HANDLEBAR_HELPER_SWITCH] = getSwitch;
+        afStructsHandleBarHelpers[HANDLEBAR_HELPER_CASE] = getCase;
+        afStructsHandleBarHelpers[HANDLEBAR_HELPER_DEFAULT] = getDefault;
+        var afStructsRowToHandleBarTemplateFileMap = [{ dbRowType: DATABASE_ROW_TYPE_AF_STRUCTS, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_AF_STRUCTS }];
+
+        const afStructsGenerationCode = await mapDatabase(db)
+            .then(templateDir => resolveTemplateDirectory(templateDir, ""))
+            .then(templates => compileTemplate(templates, [HANDLEBAR_TEMPLATE_FILE_AF_STRUCTS]))
+            .then(databaseRows => infoFromDb(databaseRows, [DATABASE_ROW_TYPE_AF_STRUCTS]))
+            .then(databaseRowsWithEnumItems => groupInfoIntoDbRow(databaseRowsWithEnumItems, { tableName: 'STRUCT_ITEMS', foreignKey: 'STRUCT_REF', primaryKey: 'STRUCT_ID', dbType: 'af-structs', columns: { NAME: "NAME", VALUE: "TYPE" } }))
+            .then(helperResolution => resolveHelper(helperResolution, afStructsHandleBarHelpers))
+            .then(resultToFile => generateDataToPreview(resultToFile, afStructsRowToHandleBarTemplateFileMap))
+            .catch(err => logError(err))
+
+        //att-storage.h generation
+        var attStorageRowToHandleBarTemplateFileMap = [{ dbRowType: DATABASE_ROW_TYPE_ATT_STORAGE, hTemplateFile: HANDLEBAR_TEMPLATE_FILE_ATT_STORAGE }];
+
+        const attStorageGenerationCode = await mapDatabase(db)
+            .then(templateDir => resolveTemplateDirectory(templateDir, ""))
+            .then(templates => compileTemplate(templates, [HANDLEBAR_TEMPLATE_FILE_ATT_STORAGE]))
+            .then(resultToFile => generateDataToPreview(resultToFile, attStorageRowToHandleBarTemplateFileMap))
+            .catch(err => logError(err))
+
         if (request.params.name === DATABASE_ROW_TYPE_CLUSTER) {
             response.json(clusterGenerationCode);
         } else if (request.params.name === DATABASE_ROW_TYPE_ENUMS) {
             response.json(enumGenerationCode);
+        } else if (request.params.name === DATABASE_ROW_TYPE_PRINT_CLUSTER) {
+            response.json(printClusterGenerationCode);
+        } else if (request.params.name === DATABASE_ROW_TYPE_AF_STRUCTS) {
+            response.json(afStructsGenerationCode);
+        } else if (request.params.name == DATABASE_ROW_TYPE_ATT_STORAGE) {
+            response.json(attStorageGenerationCode);
         }
     })
 
diff --git a/src-electron/rest/static-zcl.js b/src-electron/rest/static-zcl.js
index 82149b34..e3463b2c 100644
--- a/src-electron/rest/static-zcl.js
+++ b/src-electron/rest/static-zcl.js
@@ -45,6 +45,27 @@ function processGetEntityRequest(db, path, id, replyId, callback) {
         case 'deviceType':
             Zcl.zclDeviceTypes(db, id).then(x => callback(replyId, { data: x, title: `Device type: ${id}`, type: 'device_type' }))
             break
+        case 'endpointTypeClusters': 
+            Zcl.zclEndpointTypeClusters(db, id).then( x => callback(replyId, {data: x, type: `endpointTypeClusters`}))
+            break
+        case 'endpointTypeAttributes':
+            Zcl.zclEndpointTypeAttributes(db, id).then( x => callback(replyId, {data: x, type: `endpointTypeAttributes`}))
+            break
+        case 'endpointTypeCommands':
+            Zcl.zclEndpointTypeCommands(db, id).then( x => callback(replyId, {data: x, type: `endpointTypeCommands`}))
+            break
+        case 'endpointTypeReportableAttributes': 
+            Zcl.zclEndpointTypeReportableAttributes(db, id).then( x => callback(replyId, {data: x, type: `endpointTypeReportableAttributes`}))
+            break
+        case `endpointTypeDeviceTypeClusters`:
+            Zcl.zclDeviceTypeClusters(db, id).then ( x => callback(replyId, {data: x, type: `deviceTypeClusters`}))
+            break
+        case `endpointTypeDeviceTypeAttributes`:
+            Zcl.zclDeviceTypeAttributes(db, id).then ( x => callback(replyId, {data: x, type: `deviceTypeAttributes`}))
+            break
+        case `endpointTypeDeviceTypeCommands`:
+            Zcl.zclDeviceTypeCommands(db, id).then ( x => callback(replyId, {data: x, type: `deviceTypeCommands`}))
+            break
     }
 }
 
diff --git a/src-electron/rest/user-data.js b/src-electron/rest/user-data.js
index 44e1ff9d..4ff33a08 100644
--- a/src-electron/rest/user-data.js
+++ b/src-electron/rest/user-data.js
@@ -7,17 +7,143 @@
  */
 
 import { logInfo } from '../main-process/env'
-import { insertOrReplaceClusterState, updateKeyValue, insertEndpoint, insertEndpointType, deleteEndpointType, deleteEndpoint } from '../db/query'
 import { httpCode } from '../server/http-server'
+import { insertOrReplaceClusterState, insertOrUpdateAttributeState, insertOrUpdateCommandState, insertOrUpdateReportableAttributeState, updateKeyValue, insertEndpoint, deleteEndpoint, editEndpoint, insertEndpointType, deleteEndpointType, updateEndpointType } from '../db/query-config'
 
 export function registerSessionApi(db, app) {
     app.post('/post/cluster', (request, response) => {
         var { id, side, flag, endpointTypeId } = request.body
         insertOrReplaceClusterState(db, endpointTypeId, id, side, flag)
-            .then(() => response.status(httpCode.ok).send())
+            .then(() => response.json({
+                replyId: "zcl-endpointType-cluster-selection-response",
+                endpointTypeId: endpointTypeId,
+                id: id, 
+                side: side, 
+                flag: flag
+            }).status(httpCode.ok).send())
             .catch((err) => response.status(httpCode.badRequest).send())
     })
 
+
+    app.post('/post/attribute/update', (request, response) => {
+        var { action, endpointTypeId, id, value, listType} = request.body
+        var booleanParam = ''
+        switch (listType) {
+            case 'selectedAttributes':
+                booleanParam = 'INCLUDED'
+                break
+            case 'selectedExternal':
+                booleanParam = "EXTERNAL"
+                break
+            case 'selectedFlash':
+                booleanParam = "FLASH"
+                break
+            case 'selectedSingleton':
+                booleanParam = "SINGLETON"
+                break
+            case 'selectedBounded':
+                booleanParam = "BOUNDED"
+            case 'defaultValue':
+                booleanParam = "DEFAULT_VALUE"
+            default: 
+                break
+        }
+        switch (action) {
+            case 'boolean':
+                insertOrUpdateAttributeState(db, endpointTypeId, id, value, booleanParam).then(() => {
+                    response.json({
+                        action: action,
+                        endpointTypeId: endpointTypeId,
+                        id: id,
+                        added: value,
+                        listType: listType,
+                        replyId: 'singleAttributeState'
+                    })
+                    return response.status(httpCode.ok).send()
+                })
+                break
+            case 'text': 
+                insertOrUpdateAttributeState(db, endpointTypeId, id, value, booleanParam).then(() => {
+                    response.json({
+                        action: action, 
+                        endpointTypeId: endpointTypeId,
+                        id: id,
+                        added: value,
+                        listType: listType,
+                        replyId: 'singleAttributeState'
+                    })
+                    return response.status(httpCode.ok).send()
+                })
+            default:
+                break
+        }
+    })
+
+    app.post('/post/command/update', (request, response) => {
+        var { action, endpointTypeId, id, value, listType} = request.body
+        var booleanParam = ''
+
+        switch (listType) {
+            case 'selectedIn':
+                booleanParam = "INCOMING"
+                break
+            case 'selectedOut':
+                booleanParam = "OUTGOING"
+                break
+            default: 
+                break
+        }
+        switch (action) {
+            case 'boolean':
+                insertOrUpdateCommandState(db, endpointTypeId, id, value, booleanParam).then(() => {
+                    response.json({
+                        action: action,
+                        endpointTypeId: endpointTypeId,
+                        id: id,
+                        added: value,
+                        listType: listType,
+                        replyId: 'singleCommandState'
+                    })
+                    return response.status(httpCode.ok).send()
+                })
+                break
+            default:
+                break
+        }
+    })
+
+    app.post('/post/reportableAttribute/update', (request, response) => {
+        var { action, endpointTypeId, id, value, listType} = request.body
+        var booleanParam = ''
+        switch (listType) {
+            case 'selectedReporting':
+                booleanParam = 'INCLUDED'
+                break
+            case 'reportingMin':
+                booleanParam = "MIN_INTERVAL"
+                break
+            case 'reportingMax':
+                booleanParam = "MAX_INTERVAL"
+                break
+            case 'reportableChange':
+                booleanParam = "REPORTABLE_CHANGE"
+                break
+            default: 
+                break
+        }
+        insertOrUpdateReportableAttributeState(db, endpointTypeId, id, value, booleanParam).then(() => {
+            response.json({
+                action: action,
+                endpointTypeId: endpointTypeId,
+                id: id, 
+                added: value,
+                listType: listType,
+                replyId: 'singleReportableAttributeState'
+            })
+            return response.status(httpCode.ok).send()
+        })
+    })
+
     app.post('/post/save', (request, response) => {
         var { key, value } = request.body
         var sessionId = request.session.zapSessionId
@@ -59,6 +185,31 @@ export function registerSessionApi(db, app) {
                     })
                     return response.status(httpCode.ok).send()
                 })
+                break
+            case 'e':
+                var changeParam = ""
+                switch(context.updatedKey) {
+                    case 'endpointId': 
+                        changeParam = "ENDPOINT_ID"
+                        break
+                    case 'endpointType':
+                        changeParam = "ENDPOINT_TYPE_REF"
+                        break
+                    case 'networkId':
+                        changeParam = "NETWORK_ID"
+                        break
+                }
+                editEndpoint(db, sessionId, context.id, changeParam, context.value).then(data => {
+                    response.json({
+                        action: 'u',
+                        endpointId: context.id,
+                        updatedKey: context.updatedKey,
+                        updatedValue: context.value,
+                        replyId: "zcl-endpoint-response"
+                    })
+                    return response.status(httpCode.ok).send()
+                })
+                break
             default:
                 break
         }
@@ -98,4 +249,32 @@ export function registerSessionApi(db, app) {
                 break
         }
     })
+
+    app.post('/post/endpointType/update', (request, response) => {
+        var {action, endpointTypeId, updatedKey, updatedValue} = request.body
+        var sessionId = request.session.zapSessionId
+
+        var param = ''
+        switch (updatedKey) {
+            case 'deviceTypeRef':
+                param = "DEVICE_TYPE_REF"
+                break
+            case 'name': 
+                param = "NAME"
+            default: 
+                break
+        }
+        
+        updateEndpointType(db, sessionId, endpointTypeId, param, updatedValue).then(() => {
+            response.json({
+                action: action,
+                endpointTypeId: endpointTypeId, 
+                updatedKey: updatedKey,
+                updatedValue: updatedValue,
+                replyId: "zcl-endpointType-response"
+            })
+            return response.status(httpCode.ok).send()
+        })
+
+    })
 }
\ No newline at end of file
diff --git a/src-electron/server/http-server.js b/src-electron/server/http-server.js
index aa911b04..c5fee6c1 100644
--- a/src-electron/server/http-server.js
+++ b/src-electron/server/http-server.js
@@ -6,15 +6,15 @@
  * @module JS API: http server
  */
 
-import { logInfo, logError } from '../main-process/env.js'
+import bodyParser from 'body-parser'
 import express from 'express'
 import session from 'express-session'
-import bodyParser from 'body-parser'
 import path from 'path'
-import { ensureZapSessionId } from '../db/query.js'
-import { registerStaticZclApi } from '../rest/static-zcl.js'
+import { ensureZapSessionId } from '../db/query-session.js'
+import { logError, logInfo } from '../main-process/env.js'
 import { registerAdminApi } from '../rest/admin.js'
 import { registerGenerationApi } from '../rest/generation.js'
+import { registerStaticZclApi } from '../rest/static-zcl.js'
 import { registerSessionApi } from '../rest/user-data.js'
 
 var httpServer = null
diff --git a/src-electron/zcl/zcl-loader.js b/src-electron/zcl/zcl-loader.js
index a72cc6dd..446b256a 100644
--- a/src-electron/zcl/zcl-loader.js
+++ b/src-electron/zcl/zcl-loader.js
@@ -7,8 +7,9 @@ import fs from 'fs'
 import crc from 'crc'
 
 import { parseString } from 'xml2js'
-import { forPathCrc, updatePathCrc, insertPathCrc, insertClusters, insertDomains, insertStructs, insertBitmaps, insertEnums, insertDeviceTypes, updateClusterReferencesForDeviceTypeClusters } from '../db/query'
+import { insertClusters, insertDomains, insertStructs, insertBitmaps, insertEnums, insertDeviceTypes, updateClusterReferencesForDeviceTypeClusters,updateAttributeReferencesForDeviceTypeReferences,updateCommandReferencesForDeviceTypeReferences } from '../db/query-zcl'
 import { dbBeginTransaction, dbCommit } from '../db/db-api'
+import { forPathCrc, updatePathCrc, insertPathCrc } from '../db/query-package'
 
 const fsp = fs.promises
 
@@ -137,7 +138,8 @@ function prepareCluster(cluster) {
         max: attribute.$.max,
         isWritable: attribute.$.writable == 'true',
         defaultValue: attribute.$.default,
-        isOptional: attribute.$.optional == 'true'
+        isOptional: attribute.$.optional == 'true',
+        isReportable: attribute.$.reportable == 'true'
       })
     })
   }
@@ -202,12 +204,22 @@ function prepareDeviceType(deviceType) {
     deviceType.clusters.forEach(cluster => {
       if ('include' in cluster) {
         cluster.include.forEach(include => {
+          var attributes = []
+          var commands = []
+          if ('requireAttribute' in include) {
+            attributes = include.requireAttribute
+          }
+          if ('requireCommand' in include) {
+            commands = include.requireCommand
+          }
           ret.clusters.push({
             client: 'true' == include.$.client,
             server: 'true' == include.$.server,
             clientLocked: 'true' == include.$.clientLocked,
             serverLocked: 'true' == include.$.serverLocked,
-            clusterName: (include.$.cluster != undefined ? include.$.cluster : include._)
+            clusterName: (include.$.cluster != undefined ? include.$.cluster : include._),
+            requiredAttributes: attributes,
+            requiredCommands: commands
           })
         })
       }
@@ -254,7 +266,8 @@ function processParsedZclData(db, argument) {
 }
 
 function processPostLoading(db) {
-  return updateClusterReferencesForDeviceTypeClusters(db);
+  return updateClusterReferencesForDeviceTypeClusters(db).then(res =>
+    updateAttributeReferencesForDeviceTypeReferences(db)).then(res => updateCommandReferencesForDeviceTypeReferences(db));
 }
 
 // Promises to qualify whether zcl file needs to be reloaded.
diff --git a/src-electron/zcl/zcl-model.js b/src-electron/zcl/zcl-model.js
index 01c5ca50..917209ae 100644
--- a/src-electron/zcl/zcl-model.js
+++ b/src-electron/zcl/zcl-model.js
@@ -4,7 +4,7 @@
  * ZCL specific stuff.
  */
 
-import { selectAllClusters, selectClusterById, selectAllDomains, selectDomainById, selectAllEnums, selectEnumById, selectAllStructs, selectStructById, selectAllBitmaps, selectBitmapById, selectAllDeviceTypes, selectDeviceTypeById, selectAttributesByClusterId, selectCommandsByClusterId} from '../db/query.js'
+import { selectAllClusters, selectAllAttributes, selectAllCommands, selectClusterById, selectAllDomains, selectDomainById, selectAllEnums, selectEnumById, selectAllStructs, selectStructById, selectAllBitmaps, selectBitmapById, selectAllDeviceTypes, selectDeviceTypeById, selectAttributesByClusterId, selectCommandsByClusterId, selectEndpointTypeClustersByEndpointTypeId, selectEndpointTypeAttributesByEndpointId, selectEndpointTypeCommandsByEndpointId, selectEndpointTypeReportableAttributeByEndpointId, selectDeviceTypeClustersByDeviceTypeRef, selectDeviceTypeAttributesByDeviceTypeRef, selectDeviceTypeCommandsByDeviceTypeRef} from '../db/query-zcl.js'
 
 export function zclClusters(db, id) {
   const f = (x) => {
@@ -39,12 +39,13 @@ export function zclAttributes(db, clusterId) {
       max: x.MAX,
       isWritable: x.IS_WRITABLE,
       defaultValue: x.DEFAULT_VALUE,
-      isOptional: x.IS_OPTIONAL
+      isOptional: x.IS_OPTIONAL,
+      isReportable: x.IS_REPORTABLE
     }
   }
 
   if (clusterId == 'all') {
-    return selectAllClusters(db).then(rows => null).then(t => null)
+    return selectAllAttributes(db).then(rows => rows.map(f))
   } else {
     return selectAttributesByClusterId(db, clusterId).then(rows => rows.map(f))
   }
@@ -65,7 +66,7 @@ export function zclCommands(db, clusterId) {
   }
 
   if (clusterId == 'all') {
-    return selectAllClusters(db).then(rows => null).then(t => null)
+    return selectAllCommands(db).then(rows => rows.map(f))
   } else {
     return selectCommandsByClusterId(db, clusterId).then(rows => rows.map(f))
   }
@@ -87,7 +88,7 @@ export function zclCommands(db, clusterId) {
   }
 
   export function zclEnums(db, id) {
-    const f = (x) => {
+    const f = (x) => { 
       return {
         id: x.ENUM_ID,
         label: x.NAME,
@@ -147,3 +148,95 @@ export function zclCommands(db, clusterId) {
       return selectDeviceTypeById(db, id).then(f)
     }
   }
+
+  export function zclDeviceTypeClusters(db, deviceTypeRef) {
+    const f = (x) => {
+      zclDeviceTypeAttributes(db, deviceTypeRef)
+      return {
+        deviceTypeRef: x.DEVICE_TYPE_REF,
+        clusterRef: x.CLUSTER_REF,
+        clusterName: x.CLUSTER_NAME, 
+        includeClient: x.INCLUDE_CLIENT,
+        includeServer: x.INCLUDE_SERVER,
+        lockClient: x.LOCK_CLIENT,
+        lockServer: x.LOCK_SERVER
+      }
+    }
+    return selectDeviceTypeClustersByDeviceTypeRef(db, deviceTypeRef).then(rows => rows.map(f))
+  }
+
+  export function zclEndpointTypeClusters(db, id) {
+    const f = (x) => {
+      return {
+        endpointTypeRef: x.ENDPOINT_TYPE_REF,
+        clusterRef: x.CLUSTER_REF,
+        side: x.SIDE,
+        enabled: x.ENABLED
+      }
+    }
+    return selectEndpointTypeClustersByEndpointTypeId(db, id).then(rows => rows.map(f))
+  }
+
+  export function zclEndpointTypeAttributes(db, id) {
+    const f = (x) => {
+      return {
+        endpointTypeRef: x.ENDPOINT_TYPE_REF,
+        attributeRef: x.ATTRIBUTE_REF,
+        included: x.INCLUDED,
+        external: x.EXTERNAL,
+        flash: x.FLASH,
+        singleton: x.SINGLETON,
+        bounded: x.BOUNDED,
+        defaultValue: x.DEFAULT_VALUE
+      }
+    }
+      return selectEndpointTypeAttributesByEndpointId(db, id).then(rows => rows.map(f))
+  }
+
+  export function zclEndpointTypeCommands(db, id) {
+    const f = (x) => {
+      return {
+        endpointTypeRef: x.ENDPOINT_TYPE_REF,
+        commandRef: x.COMMAND_REF, 
+        incoming: x.INCOMING,
+        outgoing: x.OUTGOING
+      }
+    }
+    return selectEndpointTypeCommandsByEndpointId(db, id).then(rows => rows.map(f))
+  }
+
+  export function zclEndpointTypeReportableAttributes(db, id) {
+    const f = (x) => {
+      return {
+        endpointTypeRef: x.ENDPOINT_TYPE_REF,
+        attributeRef: x.ATTRIBUTE_REF,
+        included: x.INCLUDED,
+        minInterval: x.MIN_INTERVAL,
+        maxInterval: x.MAX_INTERVAL,
+        reportableChange: x.REPORTABLE_CHANGE
+      }
+    }
+    return selectEndpointTypeReportableAttributeByEndpointId(db, id).then(rows => rows.map(f))
+  }
+
+  export function zclDeviceTypeAttributes(db, id) {
+    const f = (x) => {
+      return {
+        deviceTypeClusterRef: x.DEVICE_TYPE_REF_CLUSTER_REF,
+        attributeRef: x.ATTRIBUTE_REF,
+        attributeName: x.ATTRIBUTE_NAME
+      }
+    }
+    return selectDeviceTypeAttributesByDeviceTypeRef(db, id).then(rows => rows.map(f))
+  }
+
+  export function zclDeviceTypeCommands(db, id) {
+    const f = (x) => {
+      return {
+        deviceTypeClusterRef: x.DEVICE_TYPE_REF_CLUSTER_REF,
+        commandRef: x.COMMAND_REF,
+        commandName: x.COMMAND_NAME
+      }
+    }
+    return selectDeviceTypeCommandsByDeviceTypeRef(db, id).then(rows => rows.map(f))
+  }
\ No newline at end of file
diff --git a/src/api/renderer_api.js b/src/api/renderer_api.js
new file mode 100644
index 00000000..9c1b98fb
--- /dev/null
+++ b/src/api/renderer_api.js
@@ -0,0 +1,19 @@
+// Copyright (c) 2019 Silicon Labs. All rights reserved.
+
+// The purpose of this file is to provide the API for jxbrowser
+export default function createApi () {
+  return {
+    prefix: 'zap',
+    description: 'Zap Renderer API',
+    callbacks: [
+      {
+        description: 'Save file...',
+        callback: () => alert('save!')
+      },
+      {
+        description: 'Load file...',
+        callback: () => alert('load!')
+      }
+    ]
+  }
+}
diff --git a/src/boot/axios.js b/src/boot/axios.js
index 481c1865..f587d2ba 100644
--- a/src/boot/axios.js
+++ b/src/boot/axios.js
@@ -4,7 +4,6 @@ import Vue from 'vue'
 import axios from 'axios'
 import events from 'events'
 
-console.log('Client init with axios  mode.')
 Vue.prototype.$axios = axios({ withCredentials: true })
 var eventEmitter = new events.EventEmitter()
 
diff --git a/src/boot/globalapi.js b/src/boot/globalapi.js
new file mode 100644
index 00000000..6eed1ff4
--- /dev/null
+++ b/src/boot/globalapi.js
@@ -0,0 +1,7 @@
+// Copyright (c) 2019 Silicon Labs. All rights reserved.
+
+// The purpose of this file is to populate the api for the entry points from jxbrowser.
+
+import createApi from '../api/renderer_api'
+
+window.global_renderer_api = createApi()
diff --git a/src/components/ZclAttributeView.vue b/src/components/ZclAttributeView.vue
index 05501fc9..e810146d 100644
--- a/src/components/ZclAttributeView.vue
+++ b/src/components/ZclAttributeView.vue
@@ -21,6 +21,8 @@
               v-model="selection"
               :val="props.row.id"
               indeterminate-value="false"
+              keep-color
+              :color="handleColorSelection(selection, requiredAttributes, props.row)"
               @input="handleAttributeSelection(props.row.id, selection, 'selectedAttributes')"
             />
           </q-td>
@@ -101,6 +103,27 @@ export default {
       if (arg.type === 'cluster') {
         this.$store.dispatch('zap/updateAttributes', arg.attributeData || [])
       }
+      if (arg.type === 'endpointTypeAttributes') {
+        this.$store.dispatch('zap/setAttributeStateLists', arg.data)
+      }
+      if (arg.type === 'deviceTypeAttributes') {
+        this.$store.dispatch('zap/setRequiredAttributes', arg.data)
+      }
+    })
+    this.$serverOn('singleAttributeState', (event, arg) => {
+      if (arg.action === 'boolean') {
+        this.$store.dispatch('zap/updateSelectedAttributes', {
+          id: arg.id,
+          added: arg.added,
+          listType: arg.listType,
+          view: 'attributeView'
+        })
+      } else if (arg.action === 'text') {
+        this.$store.dispatch('zap/updateAttributeDefaults', {
+          id: arg.id,
+          newDefaultValue: arg.added
+        })
+      }
     })
   },
   methods: {
@@ -112,18 +135,33 @@ export default {
       } else {
         addedValue = false
       }
-      this.$store.dispatch('zap/updateSelectedAttributes', {
-        id: id,
-        added: addedValue,
-        listType: listType,
-        view: 'attributeView'
-      })
+
+      this.$serverPost(`/attribute/update`,
+        {
+          action: 'boolean',
+          endpointTypeId: this.selectedEndpointId,
+          id: id,
+          value: addedValue,
+          listType: listType
+        })
     },
     handleAttributeDefaultChange (id, newValue) {
-      this.$store.dispatch('zap/updateAttributeDefaults', {
-        id: id,
-        newDefaultValue: newValue
-      })
+      this.$serverPost(`/attribute/update`,
+        {
+          action: 'text',
+          endpointTypeId: this.selectedEndpointId,
+          id: id,
+          value: newValue,
+          listType: 'defaultValue'
+        })
+    },
+    handleColorSelection (selectedList, recommendedList, attributeData) {
+      let relevantAttributeList = attributeData.side === 'client' ? this.selectionClusterClient : this.selectionClusterServer
+      if (recommendedList.includes(attributeData.id) && relevantAttributeList.includes(attributeData.clusterRef)) {
+        if (selectedList.includes(attributeData.id)) return 'green'
+        else return 'red'
+      }
+      return 'primary'
     }
   },
 
@@ -162,7 +200,31 @@ export default {
       get () {
         return this.$store.state.zap.attributeView.defaultValues
       }
-    }
+    },
+    selectedEndpointId: {
+      get () {
+        return this.$store.state.zap.endpointTypeView.selectedEndpointType
+      }
+    },
+    requiredDeviceTypeAttributes: {
+      get () {
+        return this.$store.state.zap.attributeView.requiredAttributes
+      }
+    },
+    requiredAttributes: {
+      get () {
+        return this.attributeData.filter(attribute => !attribute.isOptional || (this.requiredDeviceTypeAttributes.includes(attribute.id))).map(attribute => attribute.id)
+      }
+    },
+    selectionClusterClient: {
+      get () {
+        return this.$store.state.zap.clustersView.selectedClients
+      }
+    },
+    selectionClusterServer: {
+      get () {
+        return this.$store.state.zap.clustersView.selectedServers
+      } }
   },
   data () {
     return {
diff --git a/src/components/ZclClusterDetail.vue b/src/components/ZclClusterDetail.vue
index a1734c8e..ae576b91 100644
--- a/src/components/ZclClusterDetail.vue
+++ b/src/components/ZclClusterDetail.vue
@@ -1,21 +1,26 @@
 <!-- Copyright (c) 2019 Silicon Labs. All rights reserved. -->
 <template>
-  <div v-show="item.length>0">
-    <zcl-cluster-info />
-    <q-tabs v-model="tab" dense align="justify">
-      <q-tab name="attributes" label="Attributes" />
-      <q-tab name="commands" label="Commands" />
-      <q-tab name="reporting" label="Reporting" />
-    </q-tabs>
-
-    <div class="col" v-show="tab == 'attributes'">
-      <ZclAttributeView />
-    </div>
-    <div class="col" v-show="tab == 'commands'">
-      <ZclCommandView />
+  <div >
+    <div v-show="selectedEndpointId.length==0 && item.length>0">
+      Please select an endpoint type before trying to configure anything.
     </div>
-    <div class="col" v-show="tab == 'reporting'">
-      <ZclReportingView />
+    <div v-show="item.length>0 && selectedEndpointId.length>0">
+      <zcl-cluster-info />
+      <q-tabs v-model="tab" dense align="justify">
+        <q-tab name="attributes" label="Attributes" />
+        <q-tab name="commands" label="Commands" />
+        <q-tab name="reporting" label="Reporting" />
+      </q-tabs>
+
+      <div class="col" v-show="tab == 'attributes'">
+        <ZclAttributeView />
+      </div>
+      <div class="col" v-show="tab == 'commands'">
+        <ZclCommandView />
+      </div>
+      <div class="col" v-show="tab == 'reporting'">
+        <ZclReportingView />
+      </div>
     </div>
   </div>
 </template>
@@ -32,6 +37,11 @@ export default {
       get () {
         return this.$store.state.zap.clustersView.selected
       }
+    },
+    selectedEndpointId: {
+      get () {
+        return this.$store.state.zap.endpointTypeView.selectedEndpointType
+      }
     }
   },
   data () {
diff --git a/src/components/ZclClusterInfo.vue b/src/components/ZclClusterInfo.vue
index fba7068a..38f5bc8c 100644
--- a/src/components/ZclClusterInfo.vue
+++ b/src/components/ZclClusterInfo.vue
@@ -1,7 +1,7 @@
 <template>
-  <div v-show='item'>
-    <div v-show='item.label'>Cluster: {{ item.label }}</div>
-    <div v-show='item.caption'>Description: {{ item.caption }}</div>
+  <div v-show="item">
+    <div>Cluster: {{ item.label }}</div>
+    <div>Description: {{ item.caption }}</div>
   </div>
 </template>
 
@@ -9,24 +9,16 @@
 export default {
   name: 'ZclClusterInfo',
   mounted () {
-    this.$serverOn('zcl-item', (event, arg) => {
-      console.log('zcl-item:')
-      console.log(arg)
-      this.item = arg.data
-      this.title = arg.title
-      this.type = arg.type
-      this.attributeData = arg.attributeData
-      this.commandData = arg.commandData
-    })
+  },
+  computed: {
+    item: {
+      get () {
+        return this.$store.state.zap.clustersView.selected[0]
+      }
+    }
   },
   data () {
     return {
-      item: {},
-      title: '',
-      type: '',
-      attributeData: [],
-      commandData: [],
-      selection: []
     }
   }
 }
diff --git a/src/components/ZclClusterList.vue b/src/components/ZclClusterList.vue
index 75219fae..856d9b4c 100644
--- a/src/components/ZclClusterList.vue
+++ b/src/components/ZclClusterList.vue
@@ -20,8 +20,11 @@
             <q-checkbox
               dark
               class="q-mt-xs"
+              :disable="selectedEndpointId == 0"
               v-model="selectionClient"
+              keep-color
               :val="props.row.id"
+              :color="handleColorSelection(selectionClient, recommendedClients, props.row.id)"
               indeterminate-value="false"
               @input="handleClusterSelection(props.row.id, true)"
             />
@@ -30,9 +33,12 @@
             <q-checkbox
               dark
               class="q-mt-xs"
+              keep-color
+              :disable="selectedEndpointId.length == 0"
               v-model="selectionServer"
               :val="props.row.id"
               indeterminate-value="false"
+              :color="handleColorSelection(selectionServer, recommendedServers, props.row.id)"
               @input="handleClusterSelection(props.row.id, false)"
             />
           </q-td>
@@ -75,6 +81,21 @@ export default {
         return this.$store.state.zap.clustersView.selectedServers
       },
       set (val) {}
+    },
+    selectedEndpointId: {
+      get () {
+        return this.$store.state.zap.endpointTypeView.selectedEndpointType
+      }
+    },
+    recommendedClients: {
+      get () {
+        return this.$store.state.zap.clustersView.recommendedClients
+      }
+    },
+    recommendedServers: {
+      get () {
+        return this.$store.state.zap.clustersView.recommendedServers
+      }
     }
   },
 
@@ -93,10 +114,17 @@ export default {
         addedValue = false
       }
       if (isClient) {
-        this.$store.dispatch('zap/updateSelectedClients', { id: id, added: addedValue, listType: 'selectedClients', view: 'clustersView' })
+        this.$store.dispatch('zap/updateSelectedClients', { endpointTypeId: this.selectedEndpointId, id: id, added: addedValue, listType: 'selectedClients', view: 'clustersView' })
       } else {
-        this.$store.dispatch('zap/updateSelectedServers', { id: id, added: addedValue, listType: 'selectedServers', view: 'clustersView' })
+        this.$store.dispatch('zap/updateSelectedServers', { endpointTypeId: this.selectedEndpointId, id: id, added: addedValue, listType: 'selectedServers', view: 'clustersView' })
+      }
+    },
+    handleColorSelection (selectedList, recommendedList, id) {
+      if (recommendedList.includes(id)) {
+        if (selectedList.includes(id)) return 'green'
+        else return 'red'
       }
+      return 'primary'
     }
   },
 
@@ -105,6 +133,14 @@ export default {
       this.title = arg.title
       this.type = arg.type
     })
+    this.$serverOn('zcl-item', (event, arg) => {
+      if (arg.type === 'endpointTypeClusters') {
+        this.$store.dispatch('zap/setClusterList', arg.data)
+      }
+      if (arg.type === `deviceTypeClusters`) {
+        this.$store.dispatch('zap/setRecommendedClusterList', arg.data)
+      }
+    })
   },
   data () {
     return {
diff --git a/src/components/ZclCommandView.vue b/src/components/ZclCommandView.vue
index 9508a640..56601602 100644
--- a/src/components/ZclCommandView.vue
+++ b/src/components/ZclCommandView.vue
@@ -18,22 +18,24 @@
             <q-checkbox
               dark
               class="q-mt-xs"
-              v-model="selectionIn"
+              v-model="selectionOut"
               :val="props.row.id"
               indeterminate-value="false"
-              @input="handleCommandSelection(props.row.id, selectionIn,'selectedIn')"
-
+              keep-color
+              :color="handleColorSelection(selectionOut, requiredCommands, props.row.id)"
+              @input="handleCommandSelection(props.row.id, selectionOut,'selectedOut')"
             />
           </q-td>
           <q-td key="in" :props="props" auto-width>
             <q-checkbox
               dark
               class="q-mt-xs"
-              v-model="selectionOut"
+              v-model="selectionIn"
               :val="props.row.id"
               indeterminate-value="false"
-              @input="handleCommandSelection(props.row.id, selectionOut,'selectedOut')"
-
+              keep-color
+              :color="handleColorSelection(selectionOut, [], props.row.id)"
+              @input="handleCommandSelection(props.row.id, selectionIn,'selectedIn')"
             />
           </q-td>
           <q-td key="direction" :props="props" auto-width>
@@ -65,6 +67,22 @@ export default {
       if (arg.type === 'cluster') {
         this.$store.dispatch('zap/updateCommands', arg.commandData || [])
       }
+      if (arg.type === 'endpointTypeCommands') {
+        this.$store.dispatch('zap/setCommandStateLists', arg.data)
+      }
+      if (arg.type === 'deviceTypeCommands') {
+        this.$store.dispatch('zap/setRequiredCommands', arg.data)
+      }
+    })
+    this.$serverOn('singleCommandState', (event, arg) => {
+      if (arg.action === 'boolean') {
+        this.$store.dispatch('zap/updateSelectedCommands', {
+          id: arg.id,
+          added: arg.added,
+          listType: arg.listType,
+          view: 'commandView'
+        })
+      }
     })
   },
   computed: {
@@ -82,6 +100,16 @@ export default {
       get () {
         return this.$store.state.zap.commandView.selectedOut
       }
+    },
+    selectedEndpointId: {
+      get () {
+        return this.$store.state.zap.endpointTypeView.selectedEndpointType
+      }
+    },
+    requiredCommands: {
+      get () {
+        return this.$store.state.zap.commandView.requiredCommands
+      }
     }
   },
   methods: {
@@ -93,12 +121,27 @@ export default {
       } else {
         addedValue = false
       }
-      this.$store.dispatch('zap/updateSelectedCommands', {
-        id: id,
-        added: addedValue,
-        listType: listType,
-        view: 'commandView'
-      })
+      this.$serverPost(`/command/update`,
+        {
+          action: 'boolean',
+          endpointTypeId: this.selectedEndpointId,
+          id: id,
+          value: addedValue,
+          listType: listType
+        })
+      // this.$store.dispatch('zap/updateSelectedCommands', {
+      //   id: id,
+      //   added: addedValue,
+      //   listType: listType,
+      //   view: 'commandView'
+      // })
+    },
+    handleColorSelection (selectedList, recommendedList, id) {
+      if (recommendedList.includes(id)) {
+        if (selectedList.includes(id)) return 'green'
+        else return 'red'
+      }
+      return 'primary'
     }
   },
   data () {
diff --git a/src/components/ZclEndpointConfig.vue b/src/components/ZclEndpointConfig.vue
index ee39c97b..a0903fd4 100644
--- a/src/components/ZclEndpointConfig.vue
+++ b/src/components/ZclEndpointConfig.vue
@@ -51,7 +51,22 @@
       <template v-slot:body="props">
         <q-tr :props="props" clickable @click="setActiveIndex(props.row)" dark>
           <q-td key="eptId" :props="props" auto-width>
-            0x{{ endpointId[props.row.id].toString(16).padStart(4, "0") }}
+            {{getFormattedEndpointId(props.row.id)}}
+            <q-popup-edit dark dense>
+            <q-input
+              debounce="300"
+              type="text"
+              v-model="endpointId[props.row.id]"
+              dark
+              dense
+              prefix="0x"
+              mask="XXXX"
+              fill-mask="0"
+              reverse-fill-mask
+              @input="handleEndpointChange(props.row.id, 'endpointId', endpointId[props.row.id])"
+              :rules="[ val => val.length <= 4 || 'EndpointId is a 2 byte value' ]"
+            />
+            </q-popup-edit>
           </q-td>
           <q-td key="profileId" :props="props" auto-width>
             {{ (deviceTypes[endpointDeviceTypeRef[endpointType[props.row.id]]] ? deviceTypes[endpointDeviceTypeRef[endpointType[props.row.id]]].profileId.toString(16) : "").padStart(4, "0") }}
@@ -64,9 +79,31 @@
           </q-td>
           <q-td key="endpointType" :props="props" auto-width>
             {{ endpointTypeName[endpointType[props.row.id]] }}
+            <q-popup-edit dark dense>
+                <q-select
+                  filled
+                  v-model="endpointType[props.row.id]"
+                  :options="Object.keys(endpointTypeName)"
+                  :option-label="(item) => item === null ? '' : endpointTypeName[item]"
+                  label="Endpoint Type"
+                  dense
+                  dark
+                  @input="handleEndpointChange(props.row.id, 'endpointType', $event)"
+                />
+            </q-popup-edit>
           </q-td>
           <q-td key="nwkId" :props="props" auto-width>
             {{ networkId[props.row.id] }}
+            <q-popup-edit dark dense>
+            <q-input
+              debounce="300"
+              type="text"
+              v-model="networkId[props.row.id]"
+              dark
+              dense
+              @input="handleEndpointChange(props.row.id, 'networkId', networkId[props.row.id])"
+            />
+            </q-popup-edit>
           </q-td>
         </q-tr>
       </template>
@@ -94,6 +131,13 @@ export default {
             id: arg.id
           })
           break
+        case 'u':
+          this.$store.dispatch('zap/updateEndpoint', {
+            id: arg.endpointId,
+            updatedKey: arg.updatedKey,
+            updatedValue: arg.updatedValue
+          })
+          break
         default:
           break
       }
@@ -251,8 +295,24 @@ export default {
       } else {
         this.activeIndex = [index]
         this.$store.dispatch('zap/updateSelectedEndpoint', index.id)
-        this.$store.dispatch('zap/updateSelectedEndpointType', this.endpointType[index.id])
+        this.$store.dispatch('zap/updateSelectedEndpointType', {
+          endpointType: this.endpointType[index.id],
+          deviceTypeRef: this.endpointDeviceTypeRef[index.id]
+        })
       }
+    },
+    getFormattedEndpointId (endpointRef) {
+      return '0x' + this.endpointId[endpointRef].toString(16).padStart(4, '0')
+    },
+    handleEndpointChange (id, changeId, value) {
+      this.$serverPost('/endpoint', {
+        action: 'e',
+        context: {
+          id: id,
+          updatedKey: changeId,
+          value: value
+        }
+      })
     }
   }
 }
diff --git a/src/components/ZclEndpointTypeConfig.vue b/src/components/ZclEndpointTypeConfig.vue
index 80c5171e..76ded05c 100644
--- a/src/components/ZclEndpointTypeConfig.vue
+++ b/src/components/ZclEndpointTypeConfig.vue
@@ -35,6 +35,22 @@
         </q-card-actions>
         </q-card>
       </q-dialog>
+      <q-dialog v-model="confirmEptTypeUpdate">
+        <q-card>
+          <q-card-section>
+            <div class="text-h6">Please confirm</div>
+          </q-card-section>
+          <q-card-section>
+            You are trying to change the device type! This will reset all settings to the default required for the device type.
+            You will lose data!
+          </q-card-section>
+          <q-card-section align="right">
+            <q-btn flat label="Cancel" color="primary" v-close-popup />
+            <q-btn flat label="Confirm" color="primary" v-close-popup @click="setZclDeviceType(desiredZclEndpointType)"/>
+          </q-card-section>
+
+        </q-card>
+      </q-dialog>
     </div>
 
   <div class="row">
@@ -59,7 +75,7 @@
           :options="zclDeviceTypeOptions"
           :option-label="(item) => item === null ? '' : zclDeviceTypes[item].label"
           label="ZCL Device Type"
-          @input="setZclDeviceType($event)"
+          @input="showConfirmZclDeviceTypeChangeDialog($event)"
         />
       </div>
     </div>
@@ -75,23 +91,24 @@ export default {
         this.$store.dispatch('zap/updateZclDeviceTypes', arg.data || [])
 
         var indexOnOff = -1
-        var indexDoorLock = -1
+        // var indexDoorLock = -1
+
         // We kick start everything by having automatically adding a centralized endpointType using the HA-onoff deviceType
-        for (var x in this.zclDeviceTypes) {
-          if (this.zclDeviceTypes[x]['label'] === 'HA-onoff') { indexOnOff = x }
-          if (this.zclDeviceTypes[x]['label'] === 'HA-doorlock') { indexDoorLock = x }
-        }
-        let onOffEptType = {
-          name: 'Centralized',
-          deviceTypeRef: indexOnOff !== -1 ? indexOnOff : 1
-        }
+        if (this.zclEndpointTypeOptions.length < 1) {
+          for (var x in this.zclDeviceTypes) {
+            if (this.zclDeviceTypes[x]['label'] === 'HA-onoff') { indexOnOff = x }
+            //          if (this.zclDeviceTypes[x]['label'] === 'HA-doorlock') { indexDoorLock = x }
+          }
+          let onOffEptType = {
+            name: 'Centralized',
+            deviceTypeRef: indexOnOff !== -1 ? indexOnOff : 1
+          }
 
-        let doorlockEptType = {
-          name: 'Primary',
-          deviceTypeRef: indexDoorLock !== -1 ? indexDoorLock : 1
+          this.addEndpointType(onOffEptType)
+          // Server does not handle multiple requests coming in at the same time
+          // correctly well. It fails with a 'transaction in a transaction' issue
+          // this.addEndpointType(doorlockEptType)
         }
-        this.addEndpointType(onOffEptType)
-        this.addEndpointType(doorlockEptType)
       }
     })
 
@@ -112,6 +129,15 @@ export default {
             })
           }
           break
+        case 'u':
+        // update
+          if (arg.updatedKey === 'deviceTypeRef') {
+            this.$store.dispatch('zap/setDeviceTypeReference', {
+              endpointId: this.selectedEndpointType,
+              deviceTypeRef: arg.updatedValue
+            })
+          }
+          break
         default:
           break
       }
@@ -120,11 +146,18 @@ export default {
     this.$serverGet('/deviceType/all')
   },
   methods: {
+    showConfirmZclDeviceTypeChangeDialog (value) {
+      this.desiredZclEndpointType = value
+      this.confirmEptTypeUpdate = true
+    },
     setZclDeviceType (value) {
-      this.$store.dispatch('zap/setDeviceTypeReference', {
-        endpointId: this.selectedEndpointType,
-        deviceTypeRef: value
-      })
+      this.$serverPost(`/endpointType/update`,
+        {
+          action: 'u',
+          endpointTypeId: this.selectedEndpointType,
+          updatedKey: 'deviceTypeRef',
+          updatedValue: value
+        })
     },
     addEndpointType (newEndpointType) {
       let name = newEndpointType.name
@@ -140,8 +173,11 @@ export default {
         }
       )
     },
-    setSelectedEndpointType (event) {
-      this.$store.dispatch('zap/updateSelectedEndpointType', event)
+    setSelectedEndpointType (id) {
+      this.$store.dispatch('zap/updateSelectedEndpointType', {
+        endpointType: id,
+        deviceTypeRef: this.zclDeviceTypesRecord[id]
+      })
     },
     deleteEptType (selectedEndpointType) {
       this.$serverPost(`/endpointType`, {
@@ -175,6 +211,11 @@ export default {
         return this.$store.state.zap.endpointTypeView.deviceTypeRef[this.selectedEndpointType]
       }
     },
+    zclDeviceTypesRecord: {
+      get () {
+        return this.$store.state.zap.endpointTypeView.deviceTypeRef
+      }
+    },
     selectedEndpointType: {
       get () {
         return this.$store.state.zap.endpointTypeView.selectedEndpointType
@@ -197,6 +238,8 @@ export default {
       title: '',
       model: [],
       newEptTypeDialog: [],
+      confirmEptTypeUpdate: [],
+      desiredZclEndpointType: [],
       type: ''
     }
   }
diff --git a/src/components/ZclReportingView.vue b/src/components/ZclReportingView.vue
index fd422f7b..6689e69d 100644
--- a/src/components/ZclReportingView.vue
+++ b/src/components/ZclReportingView.vue
@@ -21,6 +21,8 @@
               v-model="selectedReporting"
               :val="props.row.id"
               indeterminate-value="false"
+              keep-color
+              :color="handleColorSelection(selectedReporting, requiredReporting, props.row.id)"
               @input="handleSelection(props.row.id, selectedReporting,'selectedReporting')"
             />
           </q-td>
@@ -76,11 +78,27 @@ export default {
   name: 'ZclReportingView',
   mounted () {
     this.$serverOn('zcl-item', (event, arg) => {
-      console.log('zcl-item:')
-      console.log(arg)
-      this.item = arg.data
-      this.title = arg.title
-      this.type = arg.type
+      if (arg.type === 'endpointTypeReportableAttributes') {
+        this.$store.dispatch('zap/setReportableAttributeStateLists', arg.data)
+      }
+    })
+    this.$serverOn('singleReportableAttributeState', (event, arg) => {
+      if (arg.action === 'boolean') {
+        this.$store.dispatch('zap/updateSelectedAttributes', {
+          id: arg.id,
+          added: arg.added,
+          listType: arg.listType,
+          view: 'reportingView'
+        })
+      } else if (arg.action === 'text') {
+        this.$store.dispatch('zap/updateAttributeDefaults', {
+          id: arg.id,
+          newDefaultValue: arg.added,
+          listType: arg.listType,
+          view: 'reportingView'
+
+        })
+      }
     })
   },
   computed: {
@@ -123,6 +141,16 @@ export default {
       get () {
         return this.$store.state.zap.reportingView.reportableChange
       }
+    },
+    selectedEndpointId: {
+      get () {
+        return this.$store.state.zap.endpointTypeView.selectedEndpointType
+      }
+    },
+    requiredReporting: {
+      get () {
+        return this.attributeData.filter(attribute => attribute.isReportable).map(attribute => attribute.id)
+      }
     }
   },
   methods: {
@@ -134,20 +162,32 @@ export default {
       } else {
         addedValue = false
       }
-      this.$store.dispatch('zap/updateSelectedAttributes', {
-        id: id,
-        added: addedValue,
-        listType: listType,
-        view: 'reportingView'
-      })
+
+      this.$serverPost(`/reportableAttribute/update`,
+        {
+          action: 'boolean',
+          endpointTypeId: this.selectedEndpointId,
+          id: id,
+          value: addedValue,
+          listType: listType
+        })
     },
     handleAttributeDefaultChange (id, newValue, listType) {
-      this.$store.dispatch('zap/updateAttributeDefaults', {
-        id: id,
-        newDefaultValue: newValue,
-        listType: listType,
-        view: 'reportingView'
-      })
+      this.$serverPost(`/reportableAttribute/update`,
+        {
+          action: 'text',
+          endpointTypeId: this.selectedEndpointId,
+          id: id,
+          value: newValue,
+          listType: listType
+        })
+    },
+    handleColorSelection (selectedList, recommendedList, id) {
+      if (recommendedList.includes(id)) {
+        if (selectedList.includes(id)) return 'green'
+        else return 'red'
+      }
+      return 'primary'
     }
   },
   data () {
diff --git a/src/layouts/ZclClusterLayout.vue b/src/layouts/ZclClusterLayout.vue
index defbaf1b..81cbb9cc 100644
--- a/src/layouts/ZclClusterLayout.vue
+++ b/src/layouts/ZclClusterLayout.vue
@@ -4,12 +4,12 @@
         v-model="splitterModel"
         separator-class="bg-orange"
         separator-style="width: 3px"
-        style="height: 800px"
+        style="height: 600px"
       >
         <template v-slot:before>
           <div class="q-pa-md">
-            <ZclEndpointConfig class="bg-grey-10 text-white" />
             <ZclEndpointTypeConfig class="bg-grey-10 text-white" />
+            <ZclEndpointConfig class="bg-grey-10 text-white" />
             <ZclClusterList class="bg-grey-10 text-white" />
           </div>
         </template>
diff --git a/src/layouts/ZclLayout.vue b/src/layouts/ZclLayout.vue
index 15dc25c7..8faa49a6 100644
--- a/src/layouts/ZclLayout.vue
+++ b/src/layouts/ZclLayout.vue
@@ -71,6 +71,24 @@
                       <q-item-label>enums.h</q-item-label>
                     </q-item-section>
                   </q-item>
+
+                  <q-item clickable v-close-popup @click="generationButtonText='print-cluster.h';getGeneratedFile('print-cluster')" :label="generationButtonText">
+                    <q-item-section>
+                      <q-item-label>print-cluster.h</q-item-label>
+                    </q-item-section>
+                  </q-item>
+
+                  <q-item clickable v-close-popup @click="generationButtonText='af-structs.h';getGeneratedFile('af-structs')" :label="generationButtonText">
+                    <q-item-section>
+                      <q-item-label>af-structs.h</q-item-label>
+                    </q-item-section>
+                  </q-item>
+
+                  <q-item clickable v-close-popup @click="generationButtonText='att-storage.h';getGeneratedFile('att-storage')" :label="generationButtonText">
+                    <q-item-section>
+                      <q-item-label>att-storage.h</q-item-label>
+                    </q-item-section>
+                  </q-item>
                 </q-list>
               </q-btn-dropdown>
               <div>
diff --git a/src/store/zap/actions.js b/src/store/zap/actions.js
index 59c5a508..dca42157 100644
--- a/src/store/zap/actions.js
+++ b/src/store/zap/actions.js
@@ -63,6 +63,7 @@ export function updateSelectedServers (context, selectionContext) {
   context.commit('updateInclusionList', selectionContext)
   Vue.prototype.$serverPost(`/cluster`,
     {
+      endpointTypeId: selectionContext.endpointTypeId,
       id: selectionContext.id,
       side: 'server',
       flag: selectionContext.added
@@ -73,6 +74,7 @@ export function updateSelectedClients (context, selectionContext) {
   context.commit('updateInclusionList', selectionContext)
   Vue.prototype.$serverPost(`/cluster`,
     {
+      endpointTypeId: selectionContext.endpointTypeId,
       id: selectionContext.id,
       side: 'client',
       flag: selectionContext.added
@@ -91,6 +93,12 @@ export function updateSelectedEndpoint (context, endpoint) {
 }
 
 export function setDeviceTypeReference (context, endpointIdDeviceTypeRefPair) {
+  Vue.prototype.$serverGet(`/endpointTypeDeviceTypeClusters/${endpointIdDeviceTypeRefPair.deviceTypeRef}`)
+  Vue.prototype.$serverGet(`/endpointTypeDeviceTypeAttributes/${endpointIdDeviceTypeRefPair.deviceTypeRef}`)
+  Vue.prototype.$serverGet(`/endpointTypeDeviceTypeCommands/${endpointIdDeviceTypeRefPair.deviceTypeRef}`)
+  Vue.prototype.$serverGet(`/endpointTypeClusters/${endpointIdDeviceTypeRefPair.endpointId}`)
+  Vue.prototype.$serverGet(`/endpointTypeAttributes/${endpointIdDeviceTypeRefPair.endpointId}`)
+  Vue.prototype.$serverGet(`/endpointTypeCommands/${endpointIdDeviceTypeRefPair.endpointId}`)
   context.commit('setDeviceTypeReference', endpointIdDeviceTypeRefPair)
 }
 
@@ -106,10 +114,141 @@ export function removeEndpointType (context, endpointType) {
   context.commit('removeEndpointType', endpointType)
 }
 
-export function updateSelectedEndpointType (context, endpointType) {
-  context.commit('updateSelectedEndpointType', endpointType)
+export function updateEndpoint (context, endpoint) {
+  context.commit('updateEndpoint', endpoint)
+}
+
+export function updateSelectedEndpointType (context, endpointTypeDeviceTypeRefPair) {
+  if (endpointTypeDeviceTypeRefPair != null) {
+    Vue.prototype.$serverGet(`/endpointTypeClusters/${endpointTypeDeviceTypeRefPair.endpointType}`)
+    Vue.prototype.$serverGet(`/endpointTypeAttributes/${endpointTypeDeviceTypeRefPair.endpointType}`)
+    Vue.prototype.$serverGet(`/endpointTypeCommands/${endpointTypeDeviceTypeRefPair.endpointType}`)
+    Vue.prototype.$serverGet(`/endpointTypeReportableAttributes/${endpointTypeDeviceTypeRefPair.endpointType}`)
+    Vue.prototype.$serverGet(`/endpointTypeDeviceTypeClusters/${endpointTypeDeviceTypeRefPair.deviceTypeRef}`)
+    Vue.prototype.$serverGet(`/endpointTypeDeviceTypeAttributes/${endpointTypeDeviceTypeRefPair.deviceTypeRef}`)
+    Vue.prototype.$serverGet(`/endpointTypeDeviceTypeCommands/${endpointTypeDeviceTypeRefPair.deviceTypeRef}`)
+  }
+  context.commit('updateSelectedEndpointType', endpointTypeDeviceTypeRefPair.endpointType)
 }
 
 export function deleteEndpoint (context, endpoint) {
   context.commit('deleteEndpoint', endpoint)
 }
+
+export function setClusterList (context, selectionContext) {
+  var enabledClients = []
+  var enabledServers = []
+  selectionContext.forEach(record => {
+    if (record.enabled) {
+      if (record.side === 'client') {
+        enabledClients.push(record.clusterRef)
+      } else {
+        enabledServers.push(record.clusterRef)
+      }
+    }
+  })
+  context.commit(`setClusterList`, {
+    clients: enabledClients,
+    servers: enabledServers
+  })
+}
+
+export function setAttributeStateLists (context, selectionContext) {
+  var includedAttributes = []
+  var externalAttributes = []
+  var flashAttributes = []
+  var singletonAttributes = []
+  var boundedAttributes = []
+  var defaultValue = {}
+
+  selectionContext.forEach(record => {
+    if (record.included === 1) includedAttributes.push(record.attributeRef)
+    if (record.external === 1) externalAttributes.push(record.attributeRef)
+    if (record.flash === 1) flashAttributes.push(record.attributeRef)
+    if (record.singleton === 1) singletonAttributes.push(record.attributeRef)
+    if (record.bounded === 1) boundedAttributes.push(record.attributeRef)
+    defaultValue[record.attributeRef] = record.defaultValue
+  })
+  context.commit(`setAttributeLists`, {
+    included: includedAttributes,
+    external: externalAttributes,
+    flash: flashAttributes,
+    singleton: singletonAttributes,
+    bounded: boundedAttributes,
+    defaultValue: defaultValue
+  })
+}
+
+export function setReportableAttributeStateLists (context, selectionContext) {
+  var includedAttributes = []
+  var min = {}
+  var max = {}
+  var change = {}
+
+  selectionContext.forEach(record => {
+    if (record.included === 1) includedAttributes.push(record.attributeRef)
+    min[record.attributeRef] = record.minInterval
+    max[record.attributeRef] = record.maxInterval
+    change[record.attributeRef] = record.reportableChange
+  })
+
+  context.commit(`setReportableAttributeLists`, {
+    included: includedAttributes,
+    minInterval: min,
+    maxInterval: max,
+    reportableChange: change
+  })
+}
+
+export function setCommandStateLists (context, selectionContext) {
+  var incoming = []
+  var outgoing = []
+  selectionContext.forEach(record => {
+    if (record.incoming === 1) incoming.push(record.commandRef)
+    if (record.outgoing === 1) outgoing.push(record.commandRef)
+  })
+  context.commit(`setCommandLists`, {
+    incoming: incoming,
+    outgoing: outgoing
+  })
+}
+
+// TODO (?) This does not handle/highlight prohibited clusters. For now we just keep it in here
+export function setRecommendedClusterList (context, data) {
+  console.log(data)
+  var recommendedClients = []
+  var recommendedServers = []
+  var notRecommendedClients = []
+  var notRecommendedServers = []
+
+  data.forEach(record => {
+    if (record.includeClient) recommendedClients.push(record.clusterRef)
+    else notRecommendedClients.push(record.clusterRef)
+    if (record.includeServer) recommendedServers.push(record.clusterRef)
+    else notRecommendedServers.push(record.clusterRef)
+  })
+  context.commit(`setRecommendedClusterList`, {
+    recommendedClients: recommendedClients,
+    recommendedServers: recommendedServers
+  })
+}
+
+export function setRequiredAttributes (context, data) {
+  var requiredAttributes = []
+  data.forEach(record => {
+    if (record.attributeRef) requiredAttributes.push(record.attributeRef)
+  })
+  context.commit(`setRequiredAttributesList`, {
+    requiredAttributes: requiredAttributes
+  })
+}
+
+export function setRequiredCommands (context, data) {
+  var requiredCommands = []
+  data.forEach(record => {
+    if (record.commandRef) requiredCommands.push(record.commandRef)
+  })
+  context.commit(`setRequiredCommandsList`, {
+    requiredCommands: requiredCommands
+  })
+}
diff --git a/src/store/zap/mutations.js b/src/store/zap/mutations.js
index 576c6deb..8ac6c76a 100644
--- a/src/store/zap/mutations.js
+++ b/src/store/zap/mutations.js
@@ -54,6 +54,10 @@ export function addEndpoint (state, endpoint) {
   Vue.set(state.endpointView.networkId, endpoint.id, endpoint.network)
 }
 
+export function updateEndpoint (state, context) {
+  Vue.set(state.endpointView[context.updatedKey], context.endpointId, context.updatedValue)
+}
+
 export function initializeDefaultEndpointsTypes (state, defaultEndpointsTypes) {
   defaultEndpointsTypes.forEach(endpointType => {
     if (state.endpointTypeView.name[endpointType.id] === undefined) {
@@ -125,3 +129,71 @@ export function deleteEndpoint (state, endpoint) {
   Vue.delete(state.endpointView.endpointType, endpoint.id)
   Vue.delete(state.endpointView.networkId, endpoint.id)
 }
+
+export function setClusterList (state, data) {
+  state.clustersView.selectedClients = data.clients
+  state.clustersView.selectedServers = data.servers
+}
+
+export function resetAttributeDefaults (state) {
+  state.attributeView.defaultValues = {}
+  state.attributes.forEach(attribute => {
+    Vue.set(state.attributeView.defaultValues, attribute.id, attribute.defaultValue)
+  })
+}
+
+export function resetReportableAttributeDefaults (state) {
+  state.reportingView.reportingMin = {}
+  state.reportingView.reportingMin = {}
+  state.reportingView.reportableChange = {}
+  state.attributes.forEach(attribute => {
+    Vue.set(state.reportingView.reportingMin, attribute.id, 0)
+    Vue.set(state.reportingView.reportingMax, attribute.id, 65344)
+    Vue.set(state.reportingView.reportableChange, attribute.id, 0)
+  })
+}
+
+export function setAttributeLists (state, data) {
+  state.attributeView.selectedAttributes = data.included
+  state.attributeView.selectedExternal = data.external
+  state.attributeView.selectedFlash = data.flash
+  state.attributeView.selectedSingleton = data.singleton
+  state.attributeView.selectedBounded = data.bounded
+  resetAttributeDefaults(state)
+  Object.entries(data.defaultValue).forEach(([attributeRef, defaultVal]) => {
+    Vue.set(state.attributeView.defaultValues, attributeRef, defaultVal)
+  })
+}
+
+export function setReportableAttributeLists (state, data) {
+  state.reportingView.selectedReporting = data.included
+  resetReportableAttributeDefaults(state)
+  Object.entries(data.minInterval).forEach(([attributeRef, defaultVal]) => {
+    Vue.set(state.reportingView.reportingMin, attributeRef, defaultVal)
+  })
+
+  Object.entries(data.maxInterval).forEach(([attributeRef, defaultVal]) => {
+    Vue.set(state.reportingView.reportingMax, attributeRef, defaultVal)
+  })
+  Object.entries(data.reportableChange).forEach(([attributeRef, defaultVal]) => {
+    Vue.set(state.reportingView.reportableChange, attributeRef, defaultVal)
+  })
+}
+
+export function setCommandLists (state, data) {
+  state.commandView.selectedIn = data.incoming
+  state.commandView.selectedOut = data.outgoing
+}
+
+export function setRecommendedClusterList (state, data) {
+  Vue.set(state.clustersView, 'recommendedClients', data.recommendedClients)
+  Vue.set(state.clustersView, 'recommendedServers', data.recommendedServers)
+}
+
+export function setRequiredAttributesList (state, data) {
+  Vue.set(state.attributeView, 'requiredAttributes', data.requiredAttributes)
+}
+
+export function setRequiredCommandsList (state, data) {
+  Vue.set(state.commandView, 'requiredCommands', data.requiredCommands)
+}
diff --git a/src/store/zap/state.js b/src/store/zap/state.js
index 58aac3bc..7f6d2937 100644
--- a/src/store/zap/state.js
+++ b/src/store/zap/state.js
@@ -20,7 +20,10 @@ export default function () {
     clustersView: {
       selected: [],
       selectedServers: [],
-      selectedClients: []
+      selectedClients: [],
+      // These are based off of the selected ZCL Endpoints Device Type
+      recommendedClients: [],
+      recommendedServers: []
     },
     attributeView: {
       selectedAttributes: [],
@@ -28,11 +31,15 @@ export default function () {
       selectedFlash: [],
       selectedSingleton: [],
       selectedBounded: [],
-      defaultValues: {}
+      defaultValues: {},
+      // These are based off of the selected ZCL Endpoint Device Type
+      recommendedAttributes: []
     },
     commandView: {
       selectedIn: [],
-      selectedOut: []
+      selectedOut: [],
+      // These are based off of the selected ZCL Endpoint Device Type
+      requiredCommands: []
     },
     reportingView: {
       selectedReporting: [],
diff --git a/test/generation.test.js b/test/generation.test.js
index 8b5f0106..4cbe9ad8 100644
--- a/test/generation.test.js
+++ b/test/generation.test.js
@@ -13,11 +13,11 @@ import axios from 'axios'
 import fs from "fs"
 import { version } from '../package.json'
 import { closeDatabase, initDatabase, loadSchema } from "../src-electron/db/db-api"
-import { selectCountFrom } from "../src-electron/db/query"
+import { zclPropertiesFile } from '../src-electron/main-process/args'
 import { logError, logInfo, schemaFile, setDevelopmentEnv, sqliteTestFile } from "../src-electron/main-process/env"
 import { initHttpServer, shutdownHttpServer } from "../src-electron/server/http-server"
 import { loadZcl } from "../src-electron/zcl/zcl-loader"
-import { zclPropertiesFile } from '../src-electron/main-process/args'
+import { selectCountFrom } from '../src-electron/db/query-generic'
 
 var db
 const port = 9074
@@ -75,4 +75,26 @@ describe('Session specific tests', () => {
             expect(response.data).toMatch(/\#define ZCL_BASIC_CLUSTER_ID 0x0000/);
           })
     })
+
+    test('test that there is generation data in the print-cluster.h file', () => {
+        return axios.get(`${baseUrl}/preview/print-cluster`)
+          .then((response) => {
+            expect(response.data).toMatch(/\#if defined(ZCL_USING_BASIC_CLUSTER_SERVER) || defined(ZCL_USING_BASIC_CLUSTER_CLIENT)/);
+          })
+    })
+
+    test('test that there is generation data in the af-structs.h file', () => {
+        return axios.get(`${baseUrl}/preview/af-structs`)
+          .then((response) => {
+            expect(response.data).toMatch(/typedef struct _IasAceZoneStatusResult {/);
+            expect(response.data).toMatch(/            uint8_t zoneId;/);
+          })
+    })
+
+    test('test that there is generation data in the att-storage.h file', () => {
+      return axios.get(`${baseUrl}/preview/att-storage`)
+        .then((response) => {
+          expect(response.data).toMatch(/\#define ATTRIBUTE_MASK_WRITABLE \(0x01\)/);
+        })
+  })
 })
diff --git a/test/query.test.js b/test/query.test.js
index 9d3f7d43..86cfcebf 100644
--- a/test/query.test.js
+++ b/test/query.test.js
@@ -1,10 +1,15 @@
 import fs from "fs"
 import { version } from '../package.json'
 import { closeDatabase, initDatabase, loadSchema } from "../src-electron/db/db-api"
-import { ensureZapSessionId, getPathCrc, getSessionIdFromWindowdId, insertClusters, insertPathCrc, selectAllClusters, selectAttributesByClusterId, selectClusterById, selectCommandsByClusterId, deleteEndpoint, getSessionDirtyFlag, setSessionClean } from "../src-electron/db/query"
 import { zclPropertiesFile } from "../src-electron/main-process/args"
-import { logInfo, schemaFile, sqliteTestFile } from "../src-electron/main-process/env"
+import { logInfo, schemaFile, sqliteTestFile, logError } from "../src-electron/main-process/env"
+import { createStateFromDatabase } from "../src-electron/main-process/importexport"
 import { loadZcl } from "../src-electron/zcl/zcl-loader"
+import { getPathCrc, insertPathCrc } from "../src-electron/db/query-package"
+import { insertClusters, selectAllClusters, selectClusterById, selectAttributesByClusterId, selectCommandsByClusterId } from "../src-electron/db/query-zcl"
+import { ensureZapSessionId, setSessionClean, getSessionIdFromWindowdId, getSessionDirtyFlag } from "../src-electron/db/query-session"
+import { insertEndpointType, deleteEndpoint, deleteEndpointType } from "../src-electron/db/query-config"
+import { insertFileLocation, selectFileLocation } from "../src-electron/db/query-generic"
 
 /*
  * Created Date: Friday, March 13th 2020, 7:44:12 pm
@@ -40,6 +45,15 @@ test('Path CRC queries.', () => {
         .then((c) => expect(c).toBe(crc))
 })
 
+test('File location queries.', () => {
+    return insertFileLocation(db, '/random/file/path', 'cat')
+      .then(() => selectFileLocation(db, 'cat'))
+      .then(filePath => expect(filePath).toBe('/random/file/path'))
+      .then(() => insertFileLocation(db, '/random/file/second/path', 'cat'))
+      .then(() => selectFileLocation(db, 'cat'))
+      .then(filePath => expect(filePath).toBe('/random/file/second/path'))
+})
+
 test('Simple cluster addition.', () => {
     return insertPathCrc(db, 'test', 1)
         .then((rowid) => insertClusters(db, rowid, [{
@@ -49,7 +63,7 @@ test('Simple cluster addition.', () => {
             define: 'TEST'
         }]))
         .then((rowids) => selectAllClusters(db))
-        .then((rows) => new Promise((resolve,reject) => {
+        .then((rows) => new Promise((resolve, reject) => {
             expect(rows.length).toBe(1)
             let rowid = rows[0].CLUSTER_ID
             expect(rows[0].CODE).toBe('0x1234')
@@ -57,20 +71,20 @@ test('Simple cluster addition.', () => {
             resolve(rowid)
         }))
         .then((rowid) => selectClusterById(db, rowid))
-        .then((row) => new Promise((resolve,reject) => {
+        .then((row) => new Promise((resolve, reject) => {
             expect(row.CODE).toBe('0x1234')
             expect(row.NAME).toBe('Test')
             resolve(row.CLUSTER_ID)
         }))
         .then((rowid) => {
             selectAttributesByClusterId(db, rowid)
-            .then(rows => {
-                expect(rows.length).toBe(0)
-            })
-            .then(() => selectCommandsByClusterId(db, rowid))
-            .then(rows => {
-                expect(rows.length).toBe(0)
-            })
+                .then(rows => {
+                    expect(rows.length).toBe(0)
+                })
+                .then(() => selectCommandsByClusterId(db, rowid))
+                .then(rows => {
+                    expect(rows.length).toBe(0)
+                })
         })
 })
 
@@ -93,18 +107,60 @@ describe('Session specific queries', () => {
     test('Make sure session is dirty', () => {
         var sid;
         return getSessionIdFromWindowdId(db, 666)
-         .then(data => {
-             sid = data.sessionId
-             return getSessionDirtyFlag(db, sid)
-         })
-         .then(result => {
-             expect(result).toBeTruthy()
-         })
-         .then(() => setSessionClean(db, sid))
-         .then(() => getSessionDirtyFlag(db, sid))
-         .then(result => {
-            expect(result).toBeFalsy()
-         })
+            .then(data => {
+                sid = data.sessionId
+                return getSessionDirtyFlag(db, sid)
+            })
+            .then(result => {
+                expect(result).toBeTruthy()
+            })
+            .then(() => setSessionClean(db, sid))
+            .then(() => getSessionDirtyFlag(db, sid))
+            .then(result => {
+                expect(result).toBeFalsy()
+            })
+    })
+
+    test('Make sure triggers work', () => {
+        var sid;
+        var endpointTypeId;
+        return getSessionIdFromWindowdId(db, 666)
+            .then(data => {
+                sid = data.sessionId
+                return getSessionDirtyFlag(db, sid)
+            })
+            .then(result => {
+                expect(result).toBeFalsy()
+            })
+            .then(() => insertEndpointType(db, sid, 'Test endpoint'))
+            .then((id) => {
+                endpointTypeId = id
+                return getSessionDirtyFlag(db, sid)
+            })
+            .then(result => {
+                expect(result).toBeTruthy()
+            })
+            .then(() => setSessionClean(db, sid))
+            .then(() => getSessionDirtyFlag(db, sid))
+            .then(result => {
+                expect(result).toBeFalsy()
+            })
+            .then(() => deleteEndpointType(db, endpointTypeId))
+            .then(() => getSessionDirtyFlag(db, sid))
+            .then(result => {
+                expect(result).toBeTruthy()
+            })
+    }, 2000)
+
+    test('Test state creation', () => {
+        return createStateFromDatabase(db, sid)
+          .then(state => {
+              expect(state.creator).toBe('zap')
+              expect(state.writeTime).toBeTruthy()
+          })
+          .catch(err => {
+              logError("Error", err)
+          })
     })
 
     test('Empty delete', () => {
diff --git a/test/rendererapi.test.js b/test/rendererapi.test.js
new file mode 100644
index 00000000..59010ce5
--- /dev/null
+++ b/test/rendererapi.test.js
@@ -0,0 +1,6 @@
+import createApi from "../src/api/renderer_api"
+
+test('Test structure of renderer API', () => {
+    var api = createApi()
+    expect(api).not.toBeNull()
+})
\ No newline at end of file
diff --git a/test/server.test.js b/test/server.test.js
index 4473795b..a7b51574 100644
--- a/test/server.test.js
+++ b/test/server.test.js
@@ -15,9 +15,12 @@ import { logError, setDevelopmentEnv, sqliteTestFile, logInfo, setMainDatabase,
 import fs from "fs"
 import path from 'path'
 import axios from 'axios'
-import { getAllSesionKeyValues, selectCountFrom, insertPathCrc, insertClusters, insertDomains, getAllSessions, deleteSession } from "../src-electron/db/query"
 import { exportDataIntoFile, importDataFromFile } from "../src-electron/main-process/importexport"
 import { version } from '../package.json'
+import { selectCountFrom } from "../src-electron/db/query-generic"
+import { getAllSessions, deleteSession } from "../src-electron/db/query-session"
+import { insertPathCrc } from "../src-electron/db/query-package"
+import { insertClusters, insertDomains } from "../src-electron/db/query-zcl"
 
 var db
 const port = 9073
diff --git a/test/zcl-loader.test.js b/test/zcl-loader.test.js
index 110e1484..9a58eb25 100644
--- a/test/zcl-loader.test.js
+++ b/test/zcl-loader.test.js
@@ -3,10 +3,10 @@ var sq = require('sqlite3')
 import { loadSchema, closeDatabase } from '../src-electron/db/db-api'
 import { loadZcl } from '../src-electron/zcl/zcl-loader'
 import { zclDomains, zclClusters, zclEnums, zclStructs, zclDeviceTypes, zclBitmaps } from '../src-electron/zcl/zcl-model'
-import { selectCountFrom } from '../src-electron/db/query'
 import { version } from '../package.json'
 import { schemaFile } from '../src-electron/main-process/env'
 import { zclPropertiesFile } from '../src-electron/main-process/args'
+import { selectCountFrom } from '../src-electron/db/query-generic'
 
 test('test opening and closing the database', () => {
     var db = new sq.Database(':memory:')
diff --git a/zcl/general.xml b/zcl/general.xml
index 4c234bc0..a7c180aa 100644
--- a/zcl/general.xml
+++ b/zcl/general.xml
@@ -443,7 +443,7 @@
       </description>
       <arg name="groupId" type="INT16U"/>
       <arg name="sceneId" type="INT8U"/>
-      <arg name="transitionTime" type="INT16U" introducedIn="zcl-7.0-07-5123-07"/>
+      <arg name="transitionTime" type="INT16U" introducedIn="zcl-7.0-07-5123-07" optional="1"/>
     </command>
     <command source="client" code="0x06" name="GetSceneMembership" optional="false" cli="zcl scenes get">
       <description>
diff --git a/zcl/generation-templates/af-structs.handlebars b/zcl/generation-templates/af-structs.handlebars
new file mode 100644
index 00000000..a708417b
--- /dev/null
+++ b/zcl/generation-templates/af-structs.handlebars
@@ -0,0 +1,48 @@
+// This file is generated by Simplicity Studio.  Please do not edit manually.
+//
+//
+
+// Enclosing macro to prevent multiple inclusion
+#ifndef SILABS_EMBER_AF_STRUCTS
+#define SILABS_EMBER_AF_STRUCTS
+
+{{#each type}}
+typedef struct _{{this.NAME}} {
+    {{#each this.STRUCT_ITEMS}}
+        {{#switch VALUE}}
+            {{#case 'attribute_id' ~}}uint16_t {{NAME}};{{/case ~}}           
+            {{#case 'bitmap24' ~}}uint32_t {{NAME}};{{/case ~}}
+            {{#case 'bitmap8' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'boolean' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'char_string' ~}}uint8_t* {{NAME}};{{/case ~}}
+            {{#case 'cluster_id' ~}}uint16_t {{NAME}};{{/case ~}}
+            {{#case 'data16' ~}}uint16_t {{NAME}};{{/case ~}}
+            {{#case 'date' ~}}uint32_t {{NAME}};{{/case ~}}
+            {{#case 'deviceinformationrecordsort' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'eventconfiguration' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'eventlogid' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'iaszonestatus' ~}}uint16_t {{NAME}};{{/case ~}}
+            {{#case 'ieee_address' ~}}uint8_t* {{NAME}};{{/case ~}}
+            {{#case 'int16s' ~}}int16_t {{NAME}};{{/case ~}}
+            {{#case 'int16u' ~}}uint16_t {{NAME}};{{/case ~}}
+            {{#case 'int24u' ~}}uint32_t {{NAME}};{{/case ~}}
+            {{#case 'int32u' ~}}uint32_t {{NAME}};{{/case ~}}
+            {{#case 'int48u' ~}}uint8_t* {{NAME}};{{/case ~}}
+            {{#case 'int8s' ~}}int8_t {{NAME}};{{/case ~}}
+            {{#case 'int8u' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'no_data' ~}}uint8_t* {{NAME}};{{/case ~}}
+            {{#case 'octet_string' ~}}uint8_t* {{NAME}};{{/case ~}}
+            {{#case 'pricetier' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'repaymentdebttype' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'snapshotcause' ~}}uint32_t {{NAME}};{{/case ~}}
+            {{#case 'snapshotpayloadtype' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'snapshotscheduleconfirmation' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'status' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#case 'utc_time' ~}}uint32_t {{NAME}};{{/case ~}}
+            {{#case 'enum8' ~}}uint8_t {{NAME}};{{/case ~}}
+            {{#default 'uint8_t' ~}}uint8_t {{NAME}};{{/default}}
+        {{/switch}}
+    {{/each}}
+} {{this.NAME}};
+
+{{/each}}
\ No newline at end of file
diff --git a/zcl/generation-templates/att-storage.handlebars b/zcl/generation-templates/att-storage.handlebars
new file mode 100644
index 00000000..3e551794
--- /dev/null
+++ b/zcl/generation-templates/att-storage.handlebars
@@ -0,0 +1,57 @@
+// This file is generated by Simplicity Studio.  Please do not edit manually.
+//
+//
+
+// Enclosing macro to prevent multiple inclusion
+#ifndef SILABS_ATTRIBUTE_STORAGE_GEN
+#define SILABS_ATTRIBUTE_STORAGE_GEN
+
+
+// Attribute masks modify how attributes are used by the framework
+// Attribute that has this mask is NOT read-only
+#define ATTRIBUTE_MASK_WRITABLE (0x01)
+// Attribute that has this mask is saved to a token
+#define ATTRIBUTE_MASK_TOKENIZE (0x02)
+// Attribute that has this mask has a min/max values
+#define ATTRIBUTE_MASK_MIN_MAX (0x04)
+// Manufacturer specific attribute
+#define ATTRIBUTE_MASK_MANUFACTURER_SPECIFIC (0x08)
+// Attribute deferred to external storage
+#define ATTRIBUTE_MASK_EXTERNAL_STORAGE (0x10)
+// Attribute is singleton
+#define ATTRIBUTE_MASK_SINGLETON (0x20)
+// Attribute is a client attribute
+#define ATTRIBUTE_MASK_CLIENT (0x40)
+
+
+// Cluster masks modify how clusters are used by the framework
+// Does this cluster have init function?
+#define CLUSTER_MASK_INIT_FUNCTION (0x01)
+// Does this cluster have attribute changed function?
+#define CLUSTER_MASK_ATTRIBUTE_CHANGED_FUNCTION (0x02)
+// Does this cluster have default response function?
+#define CLUSTER_MASK_DEFAULT_RESPONSE_FUNCTION (0x04)
+// Does this cluster have message sent function?
+#define CLUSTER_MASK_MESSAGE_SENT_FUNCTION (0x08)
+// Does this cluster have manufacturer specific attribute changed funciton?
+#define CLUSTER_MASK_MANUFACTURER_SPECIFIC_ATTRIBUTE_CHANGED_FUNCTION (0x10)
+// Does this cluster have pre-attribute changed function?
+#define CLUSTER_MASK_PRE_ATTRIBUTE_CHANGED_FUNCTION (0x20)
+// Cluster is a server
+#define CLUSTER_MASK_SERVER (0x40)
+// Cluster is a client
+#define CLUSTER_MASK_CLIENT (0x80)
+
+
+// Command masks modify meanings of commands
+// Is sending of this client command supported
+#define COMMAND_MASK_OUTGOING_CLIENT (0x01)
+// Is sending of this server command supported
+#define COMMAND_MASK_OUTGOING_SERVER (0x02)
+// Is receiving of this client command supported
+#define COMMAND_MASK_INCOMING_CLIENT (0x04)
+// Is receiving of this server command supported
+#define COMMAND_MASK_INCOMING_SERVER (0x08)
+// Is this command manufacturer specific?
+#define COMMAND_MASK_MANUFACTURER_SPECIFIC (0x10)
+#endif // SILABS_ATTRIBUTE_STORAGE_GEN
diff --git a/zcl/generation-templates/print-cluster.handlebars b/zcl/generation-templates/print-cluster.handlebars
new file mode 100644
index 00000000..86108293
--- /dev/null
+++ b/zcl/generation-templates/print-cluster.handlebars
@@ -0,0 +1,25 @@
+// Enclosing macro to prevent multiple inclusion
+#ifndef SILABS_PRINT_CLUSTER
+#define SILABS_PRINT_CLUSTER
+
+
+// This is the mapping of IDs to cluster names assuming a format according
+// to the "EmberAfClusterName" defined in the ZCL header.
+// The names of clusters that are not present, are removed.
+
+{{#each type}}
+#if defined(ZCL_USING_{{uppercase this.DEFINE}}_SERVER) || defined(ZCL_USING_{{uppercase this.DEFINE}}_CLIENT)
+    #define SILABS_PRINTCLUSTER_{{uppercase this.DEFINE}} {ZCL_{{uppercase this.DEFINE}}_ID, {{this.CODE}}, {{this.NAME}} },
+#else
+    #define SILABS_PRINTCLUSTER_{{uppercase this.DEFINE}}
+#endif
+
+{{/each}}
+
+#define CLUSTER_IDS_TO_NAMES \
+{{#each type}}
+    #define SILABS_PRINTCLUSTER_{{uppercase this.DEFINE}} \
+{{/each}}
+
+#define MAX_CLUSTER_NAME_LENGTH  {{largestStringInArray type}}
+#endif // SILABS_PRINT_CLUSTER
\ No newline at end of file
diff --git a/zcl/wwah-silabs.xml b/zcl/wwah-silabs.xml
index 15d81497..7a00ffc8 100644
--- a/zcl/wwah-silabs.xml
+++ b/zcl/wwah-silabs.xml
@@ -1,80 +1,79 @@
-<?xml version="1.0"?>
 <configurator>
-  <domain name="Works With All Hubs"/>
+  <domain name="Works With All Hubs" />
+
   <enum name="WwahIasZoneEnrollmentMode" type="ENUM8">
-    <item name="TripToPair" value="0x00"/>
-    <item name="AutoEnrollmentResponse" value="0x01"/>
-    <item name="Request" value="0x02"/>
+    <item name="TripToPair"                 value="0x00" />
+    <item name="AutoEnrollmentResponse"     value="0x01" />
+    <item name="Request"                    value="0x02" />
   </enum>
+
   <enum name="WwahPowerNotificationReason" type="ENUM8">
-    <item name="Unknown" value="0x00"/>
-    <item name="Battery" value="0x01"/>
-    <item name="Brownout" value="0x02"/>
-    <item name="Watchdog" value="0x03"/>
-    <item name="ResetPin" value="0x04"/>
-    <item name="MemoryHardwareFault" value="0x05"/>
-    <item name="SofwareException" value="0x06"/>
-    <item name="OtaBootloadSuccess" value="0x07"/>
-    <item name="SoftwareReset" value="0x08"/>
-    <item name="PowerButton" value="0x09"/>
-    <item name="Temperature" value="0x0A"/>
-    <item name="BootloadFailure" value="0x0B"/>
+    <item name="Unknown"                value="0x00" />
+    <item name="Battery"                value="0x01" />
+    <item name="Brownout"               value="0x02" />
+    <item name="Watchdog"               value="0x03" />
+    <item name="ResetPin"               value="0x04" />
+    <item name="MemoryHardwareFault"    value="0x05" />
+    <item name="SofwareException"       value="0x06" />
+    <item name="OtaBootloadSuccess"     value="0x07" />
+    <item name="SoftwareReset"          value="0x08" />
+    <item name="PowerButton"            value="0x09" />
+    <item name="Temperature"            value="0x0A" />
+    <item name="BootloadFailure"        value="0x0B" />
   </enum>
+
   <struct name="WwahBeaconSurvey">
-    <item name="deviceShort" type="INT16U"/>
-    <item name="rssi" type="INT8U"/>
+    <item name="deviceShort"        type="INT16U"/>
+    <item name="rssi"               type="INT8U"/>
     <item name="classificationMask" type="INT8U"/>
   </struct>
+
   <struct name="WwahClusterStatusToUseTC">
-    <item name="clusterId" type="CLUSTER_ID"/>
-    <item name="status" type="Status"/>
+    <item name="clusterId"          type="CLUSTER_ID"/>
+    <item name="status"             type="Status"/>
   </struct>
-  <cluster manufacturerCode="0x1217" singleton="true">
-    <!-- Amazon -->
-    <name>SL Works With All Hubs</name>
-    <!-- Aligned with 17-01067-023-WWAH ZCL Cluster Definition -->
+
+  <cluster manufacturerCode="0x1217" singleton="true"> <!-- Amazon -->
+    <name>SL Works With All Hubs</name><!-- Aligned with 17-01067-023-WWAH ZCL Cluster Definition -->
     <domain>Works With All Hubs</domain>
     <description>Silicon Labs proprietary attributes and commands for Works With All Hubs functional extensions.</description>
-    <code>0xFC57</code>
-    <!-- 0xFCxx for proprietary cluster ID; 0x57 for 'W' -->
+    <code>0xFC57</code> <!-- 0xFCxx for proprietary cluster ID; 0x57 for 'W' -->
     <define>SL_WWAH_CLUSTER</define>
     <client tick="false" init="false">true</client>
     <server tick="false" init="false">true</server>
-    <!-- attribute side="server" code="0x0000" define="NOT_DEFINED"></attribute -->
-    <!-- removed from spec Version 023 -->
-    <!-- attribute side="server" code="0x0001" define="NOT_DEFINED"></attribute -->
-    <!-- removed from spec Version 012 -->
-    <attribute side="server" code="0x0002" define="SL_DISABLE_OTA_DOWNGRADES" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x00" optional="false">disable ota downgrades</attribute>
-    <attribute side="server" code="0x0003" define="SL_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x01" optional="false">mgmt leave without rejoin enabled</attribute>
-    <attribute side="server" code="0x0004" define="SL_NWK_RETRY_COUNT" type="INT8U" min="0x03" max="0xFF" writable="false" default="0xFF" optional="false">network retry count</attribute>
-    <attribute side="server" code="0x0005" define="SL_MAC_RETRY_COUNT" type="INT8U" min="0x03" max="0xFF" writable="false" default="0xFF" optional="false">mac retry count</attribute>
-    <attribute side="server" code="0x0006" define="SL_ROUTER_CHECKIN_ENABLED" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x00" optional="false">router checkin enabled</attribute>
-    <attribute side="server" code="0x0007" define="SL_TOUCHLINK_INTERPAN_ENABLED" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x00" optional="false">touchlink interpan enabled</attribute>
-    <attribute side="server" code="0x0008" define="SL_WWAH_PARENT_CLASSIFICATION_ENABLED" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x00" optional="false">wwah parent classification enabled</attribute>
-    <attribute side="server" code="0x0009" define="SL_WWAH_APP_EVENT_RETRY_ENABLED" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x01" optional="false">wwah app event retry enabled</attribute>
-    <attribute side="server" code="0x000A" define="SL_WWAH_APP_EVENT_RETRY_QUEUE_SIZE" type="INT8U" min="0x0A" max="0xFF" writable="false" default="0x0A" optional="false">wwah app event retry queue size</attribute>
-    <attribute side="server" code="0x000B" define="SL_WWAH_REJOIN_ENABLED" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x00" optional="false">wwah rejoin enabled</attribute>
-    <attribute side="server" code="0x000C" define="SL_MAC_POLL_CCA_WAIT_TIME" type="INT8U" min="0x00" max="0xFF" writable="false" default="0x03" optional="false">mac poll cca wait time</attribute>
-    <attribute side="server" code="0x000D" define="SL_CONFIGURATION_MODE_ENABLED" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x01" optional="false">configuration mode enabled</attribute>
-    <attribute side="server" code="0x000E" define="SL_CURRENT_DEBUG_REPORT_ID" type="INT8U" min="0x00" max="0xFF" writable="false" default="0x00" optional="false">current debug report id</attribute>
-    <attribute side="server" code="0x000F" define="SL_TC_SECURITY_ON_NTWK_KEY_ROTATION_ENABLED" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x00" optional="false">tc security on ntwk key rotation enabled</attribute>
-    <attribute side="server" code="0x0010" define="SL_WWAH_BAD_PARENT_RECOVERY_ENABLED" type="BOOLEAN" min="0x00" max="0x01" writable="false" default="0x00" optional="false">wwah bad parent recovery enabled</attribute>
-    <attribute side="server" code="0x0011" define="SL_PENDING_NETWORK_UPDATE_CHANNEL" type="INT8U" min="0x00" max="0xFF" writable="false" default="0xFF" optional="false">pending network update channel</attribute>
-    <attribute side="server" code="0x0012" define="SL_PENDING_NETWORK_UPDATE_PANID" type="INT16U" min="0x0000" max="0xFFFF" writable="false" default="0xFFFF" optional="false">pending network update pan id</attribute>
-    <attribute side="server" code="0x0013" define="SL_OTA_MAX_OFFLINE_DURATION" type="INT16U" min="0x0000" max="0xFFFF" writable="false" default="0x0000" optional="false">ota max offline duration</attribute>
+    <!-- attribute side="server" code="0x0000" define="NOT_DEFINED"></attribute --> <!-- removed from spec Version 023 -->
+    <!-- attribute side="server" code="0x0001" define="NOT_DEFINED"></attribute --> <!-- removed from spec Version 012 -->
+    <attribute side="server" code="0x0002" define="SL_DISABLE_OTA_DOWNGRADES"                   type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x00"               optional="false">disable ota downgrades</attribute>
+    <attribute side="server" code="0x0003" define="SL_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED"        type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x01"               optional="false">mgmt leave without rejoin enabled</attribute>
+    <attribute side="server" code="0x0004" define="SL_NWK_RETRY_COUNT"                          type="INT8U"        min="0x03"               max="0xFF"               writable="false" default="0xFF"               optional="false">network retry count</attribute>
+    <attribute side="server" code="0x0005" define="SL_MAC_RETRY_COUNT"                          type="INT8U"        min="0x03"               max="0xFF"               writable="false" default="0xFF"               optional="false">mac retry count</attribute>
+    <attribute side="server" code="0x0006" define="SL_ROUTER_CHECKIN_ENABLED"                   type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x00"               optional="false">router checkin enabled</attribute>
+    <attribute side="server" code="0x0007" define="SL_TOUCHLINK_INTERPAN_ENABLED"               type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x00"               optional="false">touchlink interpan enabled</attribute>
+    <attribute side="server" code="0x0008" define="SL_WWAH_PARENT_CLASSIFICATION_ENABLED"       type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x00"               optional="false">wwah parent classification enabled</attribute>
+    <attribute side="server" code="0x0009" define="SL_WWAH_APP_EVENT_RETRY_ENABLED"             type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x01"               optional="false">wwah app event retry enabled</attribute>
+    <attribute side="server" code="0x000A" define="SL_WWAH_APP_EVENT_RETRY_QUEUE_SIZE"          type="INT8U"        min="0x0A"               max="0xFF"               writable="false" default="0x0A"               optional="false">wwah app event retry queue size</attribute>
+    <attribute side="server" code="0x000B" define="SL_WWAH_REJOIN_ENABLED"                      type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x00"               optional="false">wwah rejoin enabled</attribute>
+    <attribute side="server" code="0x000C" define="SL_MAC_POLL_FAILURE_WAIT_TIME"               type="INT8U"        min="0x00"               max="0xFF"               writable="false" default="0x03"               optional="false">mac poll failure wait time</attribute>
+    <attribute side="server" code="0x000D" define="SL_CONFIGURATION_MODE_ENABLED"               type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x01"               optional="false">configuration mode enabled</attribute>
+    <attribute side="server" code="0x000E" define="SL_CURRENT_DEBUG_REPORT_ID"                  type="INT8U"        min="0x00"               max="0xFF"               writable="false" default="0x00"               optional="false">current debug report id</attribute>
+    <attribute side="server" code="0x000F" define="SL_TC_SECURITY_ON_NTWK_KEY_ROTATION_ENABLED" type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x00"               optional="false">tc security on ntwk key rotation enabled</attribute>
+    <attribute side="server" code="0x0010" define="SL_WWAH_BAD_PARENT_RECOVERY_ENABLED"         type="BOOLEAN"      min="0x00"               max="0x01"               writable="false" default="0x00"               optional="false">wwah bad parent recovery enabled</attribute>
+    <attribute side="server" code="0x0011" define="SL_PENDING_NETWORK_UPDATE_CHANNEL"           type="INT8U"        min="0x00"               max="0xFF"               writable="false" default="0xFF"               optional="false">pending network update channel</attribute>
+    <attribute side="server" code="0x0012" define="SL_PENDING_NETWORK_UPDATE_PANID"             type="INT16U"       min="0x0000"             max="0xFFFF"             writable="false" default="0xFFFF"             optional="false">pending network update pan id</attribute>
+    <attribute side="server" code="0x0013" define="SL_OTA_MAX_OFFLINE_DURATION"                 type="INT16U"       min="0x0000"             max="0xFFFF"             writable="false" default="0x0000"             optional="false">ota max offline duration</attribute>
     <command source="client" code="0x00" name="EnableApsLinkKeyAuthorization" optional="false" cli="zcl sl-wwah enable-aps-link-key-auth">
       <description>
         Enable enforcement of APS-level security for all cluster commands.
       </description>
       <arg name="numberExemptClusters" type="INT8U"/>
-      <arg name="clusterId" type="CLUSTER_ID" array="true" presentIf="numberExemptClusters!=0"/>
+      <arg name="clusterId"            type="CLUSTER_ID" array="true" presentIf="numberExemptClusters!=0"/>
     </command>
     <command source="client" code="0x01" name="DisableApsLinkKeyAuthorization" optional="false" cli="zcl sl-wwah disable-aps-link-key-auth">
       <description>
         Disable enforcement of APS-level security for all cluster commands.
       </description>
       <arg name="numberExemptClusters" type="INT8U"/>
-      <arg name="clusterId" type="CLUSTER_ID" array="true" presentIf="numberExemptClusters!=0"/>
+      <arg name="clusterId"            type="CLUSTER_ID" array="true" presentIf="numberExemptClusters!=0"/>
     </command>
     <command source="client" code="0x02" name="ApsLinkKeyAuthorizationQuery" optional="false" cli="zcl sl-wwah query-aps-link-key-auth">
       <description>
@@ -92,9 +91,9 @@
         Enable WWAH App Event retry algorithm.
       </description>
       <arg name="firstBackoffTimeSeconds" type="INT8U"/>
-      <arg name="backoffSeqCommonRatio" type="INT8U"/>
-      <arg name="maxBackoffTimeSeconds" type="INT32U"/>
-      <arg name="maxRedeliveryAttempts" type="INT8U"/>
+      <arg name="backoffSeqCommonRatio"   type="INT8U"/>
+      <arg name="maxBackoffTimeSeconds"   type="INT32U"/>
+      <arg name="maxRedeliveryAttempts"   type="INT8U"/>
     </command>
     <command source="client" code="0x05" name="DisableWwahAppEventRetryAlgorithm" optional="false" cli="zcl sl-wwah disable-app-event-retry-alg">
       <description>
@@ -110,11 +109,11 @@
       <description>
         Enable WWAH rejoin algorithm.
       </description>
-      <arg name="fastRejoinTimeoutSeconds" type="INT16U"/>
+      <arg name="fastRejoinTimeoutSeconds"      type="INT16U"/>
       <arg name="durationBetweenRejoinsSeconds" type="INT16U"/>
       <arg name="fastRejoinFirstBackoffSeconds" type="INT16U"/>
-      <arg name="maxBackoffTimeSeconds" type="INT16U"/>
-      <arg name="maxBackoffIterations" type="INT16U"/>
+      <arg name="maxBackoffTimeSeconds"         type="INT16U"/>
+      <arg name="maxBackoffIterations"          type="INT16U"/>
     </command>
     <command source="client" code="0x08" name="DisableWwahRejoinAlgorithm" optional="false" cli="zcl sl-wwah disable-rejoin-alg">
       <description>
@@ -143,9 +142,9 @@
         Disable device from periodically checking connectivity with Zigbee Coordinator.
       </description>
     </command>
-    <command source="client" code="0x0D" name="SetMacPollCcaWaitTime" optional="false" cli="zcl sl-wwah set-mac-poll-cca-wait-time">
+    <command source="client" code="0x0D" name="SetMacPollFailureWaitTime" optional="false" cli="zcl sl-wwah set-mac-poll-fail-wait-time">
       <description>
-        Set MAC poll CCA wait time.
+        Set MAC poll failure wait time.
       </description>
       <arg name="waitTime" type="INT8U"/>
     </command>
@@ -161,7 +160,7 @@
         Require all unicast commands to have APS ACKs enabled.
       </description>
       <arg name="numberExemptClusters" type="INT8U"/>
-      <arg name="clusterId" type="CLUSTER_ID" array="true" presentIf="numberExemptClusters!=0"/>
+      <arg name="clusterId"            type="CLUSTER_ID" array="true" presentIf="numberExemptClusters!=0"/>
     </command>
     <command source="client" code="0x10" name="RemoveApsAcksOnUnicastsRequirement" optional="false" cli="zcl sl-wwah disable-require-aps-ack-unicast">
       <description>
@@ -240,18 +239,18 @@
         Use only the Trust Center as cluster server for the set of clusters specified.
       </description>
       <arg name="numberOfClusters" type="INT8U"/>
-      <arg name="clusterId" type="CLUSTER_ID" array="true" presentIf="numberOfClusters!=0"/>
+      <arg name="clusterId"        type="CLUSTER_ID" array="true" presentIf="numberOfClusters!=0"/>
     </command>
     <command source="client" code="0x1F" name="TrustCenterForClusterServerQuery" optional="false" cli="zcl sl-wwah query-tc-for-cluster-server">
       <description>
         Causes device to send an appropriate Trust Center for Cluster Server Query Response command.
       </description>
-    </command>
+    </command>    
     <command source="server" code="0x00" name="ApsLinkKeyAuthorizationQueryResponse" optional="false">
       <description>
         Command description for SlAPSLinkKeyAuthorizationQueryResponse
       </description>
-      <arg name="clusterId" type="CLUSTER_ID"/>
+      <arg name="clusterId"            type="CLUSTER_ID"/>
       <arg name="apsLinkKeyAuthStatus" type="BOOLEAN"/>
     </command>
     <command source="server" code="0x01" name="PoweringOffNotification" optional="false">
@@ -284,54 +283,53 @@
         Command description for SlAPSAckEnablementQueryResponse
       </description>
       <arg name="numberExemptClusters" type="INT8U"/>
-      <arg name="clusterId" type="CLUSTER_ID" array="true" presentIf="numberExemptClusters!=0"/>
+      <arg name="clusterId"            type="CLUSTER_ID" array="true" presentIf="numberExemptClusters!=0"/>
     </command>
     <command source="server" code="0x05" name="PowerDescriptorChange" optional="false">
       <description>
         Command description for SlPowerDescriptorChange
       </description>
-      <arg name="currentPowerMode" type="INT32U"/>
-      <arg name="availablePowerSources" type="INT32U"/>
-      <arg name="currentPowerSource" type="INT32U"/>
+      <arg name="currentPowerMode"        type="INT32U"/>
+      <arg name="availablePowerSources"   type="INT32U"/>
+      <arg name="currentPowerSource"      type="INT32U"/>
       <arg name="currentPowerSourceLevel" type="INT32U"/>
     </command>
     <command source="server" code="0x06" name="NewDebugReportNotification" optional="false">
       <description>
         Command description for SlNewDebugReportNotification
       </description>
-      <arg name="debugReportId" type="INT8U"/>
+      <arg name="debugReportId"   type="INT8U"/>
       <arg name="debugReportSize" type="INT32U"/>
     </command>
     <command source="server" code="0x07" name="DebugReportQueryResponse" optional="false">
       <description>
         Command description for SlDebugReportQueryResponse
       </description>
-      <arg name="debugReportId" type="INT8U"/>
-      <arg name="debugReportData" type="INT8U" array="true"/>
-      <!-- OPAQUE -->
+      <arg name="debugReportId"   type="INT8U"/>
+      <arg name="debugReportData" type="INT8U" array="true"/> <!-- OPAQUE -->
     </command>
     <command source="server" code="0x08" name="TrustCenterForClusterServerQueryResponse" optional="false">
       <description>
         Command description for SlTrustCenterForClusterServerQueryResponse
       </description>
       <arg name="numberOfClusters" type="INT8U"/>
-      <arg name="clusterId" type="CLUSTER_ID" array="true" presentIf="numberOfClusters!=0"/>
+      <arg name="clusterId"        type="CLUSTER_ID" array="true" presentIf="numberOfClusters!=0"/>
     </command>
     <command source="server" code="0x09" name="SurveyBeaconsResponse" optional="false">
       <description>
         Command description for SlSurveyBeaconsResponse
       </description>
       <arg name="numberOfBeacons" type="INT8U"/>
-      <arg name="beacon" type="WwahBeaconSurvey" array="true" presentIf="numberOfBeacons!=0"/>
+      <arg name="beacon"          type="WwahBeaconSurvey" array="true" presentIf="numberOfBeacons!=0"/>
     </command>
     <command source="server" code="0x9E" name="UseTrustCenterForClusterServerResponse" optional="false">
       <!-- This extra command's integration into the spec is being discussed. Do not remove if updating XML -->
       <description>
         Command description for SlUseTrustCenterForClusterServerResponse
       </description>
-      <arg name="status" type="Status"/>
+      <arg name="status"              type="Status"/>
       <arg name="clusterStatusLength" type="INT8U"/>
-      <arg name="clusterStatus" type="WwahClusterStatusToUseTC" array="true" presentIf="clusterStatusLength!=0"/>
+      <arg name="clusterStatus"       type="WwahClusterStatusToUseTC" array="true" presentIf="clusterStatusLength!=0"/>
     </command>
   </cluster>
 </configurator>
-- 
GitLab