Added back in Bazel tests for gui2-fw-lib and gui2-topo-lib

Also used a named path in typescript for gui2-fw-lib

Change-Id: I7233565e53b9b86e1766228ecc96b21ea6f7499d
diff --git a/.bazelrc b/.bazelrc
index 66fa12d..3470b4c 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -29,7 +29,10 @@
 build --incompatible_generated_protos_in_virtual_imports=false
 build --incompatible_depset_union=false
 
+# For bazelbuild/rules_nodejs
+common --experimental_allow_incremental_repository_updates
 build --define=angular_ivy_enabled=True
+build --action_env=CHROME_BIN=/usr/bin/chromium-browser
 
 test --test_summary=terse
 test --test_output=errors
diff --git a/.gitignore b/.gitignore
index a068895..93798b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,20 @@
 out/
 
 bazel-*
+
+web/gui2/node_modules/
+web/gui2/documentation/
+web/gui2/dist/
+web/gui2/.pki/
+web/gui2/.cache/
+web/gui2/.npm/
+web/gui2/src/main/webapp/**/*.js
+!web/gui2/src/main/webapp/rxjs_shims.js
+!web/gui2/src/main/webapp/rollup.config.js
+web/gui2/e2e/**/*.js
+web/gui2-fw-lib/**/*.js
+web/gui2-topo-lib/**/*.js
+apps/faultmanagement/fm-gui2-lib/**/*.js
+apps/roadm/web/roadm-gui/**/*.js
+tools/package/archetypes/ui2/src/main/resources/archetype-resources/web/__artifactId__-gui/dist/
+tools/package/archetypes/ui2/src/main/resources/archetype-resources/web/__artifactId__-gui/projects/__artifactId__-gui-lib/src/**/*.js
diff --git a/BUILD b/BUILD
index b70aef7..881deaf 100644
--- a/BUILD
+++ b/BUILD
@@ -197,10 +197,3 @@
     ],
     mode = "fix",
 )
-
-# This export allows targets in other packages to reference files that live
-# in this package.
-# TODO Try to move this in to /web/gui2-fw-lib when possible
-exports_files([
-    "tsconfig.json",
-])
diff --git a/WORKSPACE b/WORKSPACE
index 480c76d..0df3a32 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -124,9 +124,9 @@
 generate_gnoi()
 
 # For GUI2 build
-RULES_NODEJS_VERSION = "1.0.0"
+RULES_NODEJS_VERSION = "1.0.1"
 
-RULES_NODEJS_SHA256 = "3887b948779431ac443e6a64f31b9e1e17b8d386a31eebc50ec1d9b0a6cabd2b"
+RULES_NODEJS_SHA256 = "e1a0d6eb40ec89f61a13a028e7113aa3630247253bcb1406281b627e44395145"
 
 load("//tools/build/bazel:topo_workspace.bzl", "generate_topo_device")
 
diff --git a/apps/faultmanagement/fm-gui2-lib/.gitignore b/apps/faultmanagement/fm-gui2-lib/.gitignore
deleted file mode 100644
index ceeedea..0000000
--- a/apps/faultmanagement/fm-gui2-lib/.gitignore
+++ /dev/null
@@ -1,42 +0,0 @@
-# See http://help.github.com/ignore-files/ for more about ignoring files.
-
-# compiled output
-/dist
-/tmp
-/out-tsc
-
-# dependencies
-/node_modules
-
-# IDEs and editors
-/.idea
-.project
-.classpath
-.c9/
-*.launch
-.settings/
-*.sublime-workspace
-
-# IDE - VSCode
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-
-# misc
-/.sass-cache
-/connect.lock
-/coverage
-/libpeerconnection.log
-npm-debug.log
-yarn-error.log
-testem.log
-/typings
-
-# System Files
-.DS_Store
-Thumbs.db
-
-# ONOS temp CSS files
-/projects/fm-gui2-lib/fw
diff --git a/apps/faultmanagement/fm-gui2-lib/BUILD.bazel b/apps/faultmanagement/fm-gui2-lib/BUILD.bazel
index 4288f9d..6696777 100644
--- a/apps/faultmanagement/fm-gui2-lib/BUILD.bazel
+++ b/apps/faultmanagement/fm-gui2-lib/BUILD.bazel
@@ -32,6 +32,7 @@
         "**/*.css",
         "**/*.html",
     ]),
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/apps/faultmanagement/fm-gui2-lib/lib/alarmdetails/alarmdetails.component.spec.ts b/apps/faultmanagement/fm-gui2-lib/lib/alarmdetails/alarmdetails.component.spec.ts
index 004617e..928c81e 100644
--- a/apps/faultmanagement/fm-gui2-lib/lib/alarmdetails/alarmdetails.component.spec.ts
+++ b/apps/faultmanagement/fm-gui2-lib/lib/alarmdetails/alarmdetails.component.spec.ts
@@ -23,7 +23,7 @@
     LogService,
     WebSocketService,
     IconComponent
-} from '../../../../../web/gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { DebugElement } from '@angular/core';
diff --git a/apps/faultmanagement/fm-gui2-lib/lib/alarmdetails/alarmdetails.component.ts b/apps/faultmanagement/fm-gui2-lib/lib/alarmdetails/alarmdetails.component.ts
index bcbb704..6300683 100644
--- a/apps/faultmanagement/fm-gui2-lib/lib/alarmdetails/alarmdetails.component.ts
+++ b/apps/faultmanagement/fm-gui2-lib/lib/alarmdetails/alarmdetails.component.ts
@@ -21,7 +21,7 @@
     LogService,
     DetailsPanelBaseImpl,
     WebSocketService,
-} from '../../../../../web/gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * ONOS GUI -- Alarm Details Component extends TableBaseImpl
diff --git a/apps/faultmanagement/fm-gui2-lib/lib/alarmtable/alarmtable.component.spec.ts b/apps/faultmanagement/fm-gui2-lib/lib/alarmtable/alarmtable.component.spec.ts
index ba36a98..5d95f04 100644
--- a/apps/faultmanagement/fm-gui2-lib/lib/alarmtable/alarmtable.component.spec.ts
+++ b/apps/faultmanagement/fm-gui2-lib/lib/alarmtable/alarmtable.component.spec.ts
@@ -25,7 +25,7 @@
     IconComponent,
     LogService,
     TableFilterPipe, LoadingComponent,
-} from '../../../../../web/gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 import { of } from 'rxjs';
 import { } from 'jasmine';
diff --git a/apps/faultmanagement/fm-gui2-lib/lib/alarmtable/alarmtable.component.ts b/apps/faultmanagement/fm-gui2-lib/lib/alarmtable/alarmtable.component.ts
index 9d50e11..7298cd2 100644
--- a/apps/faultmanagement/fm-gui2-lib/lib/alarmtable/alarmtable.component.ts
+++ b/apps/faultmanagement/fm-gui2-lib/lib/alarmtable/alarmtable.component.ts
@@ -20,7 +20,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../web/gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * Model of the response from the WebSocket
diff --git a/apps/faultmanagement/fm-gui2-lib/lib/fm-gui2-lib.module.ts b/apps/faultmanagement/fm-gui2-lib/lib/fm-gui2-lib.module.ts
index 85e09b6..d94f108 100644
--- a/apps/faultmanagement/fm-gui2-lib/lib/fm-gui2-lib.module.ts
+++ b/apps/faultmanagement/fm-gui2-lib/lib/fm-gui2-lib.module.ts
@@ -19,7 +19,7 @@
 import {RouterModule} from '@angular/router';
 import {
   Gui2FwLibModule,
-} from '../../../../web/gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {AlarmTableComponent} from './alarmtable/alarmtable.component';
 import {AlarmDetailsComponent} from './alarmdetails/alarmdetails.component';
 
diff --git a/apps/roadm/web/roadm-gui/.gitignore b/apps/roadm/web/roadm-gui/.gitignore
deleted file mode 100644
index 0d18a95..0000000
--- a/apps/roadm/web/roadm-gui/.gitignore
+++ /dev/null
@@ -1,43 +0,0 @@
-# See http://help.github.com/ignore-files/ for more about ignoring files.
-
-# compiled output
-/dist
-/tmp
-/out-tsc
-
-# dependencies
-/node_modules
-/node
-/etc
-
-# IDEs and editors
-/.idea
-.project
-.classpath
-.c9/
-*.launch
-.settings/
-*.sublime-workspace
-
-# IDE - VSCode
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-
-# misc
-/.sass-cache
-/connect.lock
-/coverage
-/libpeerconnection.log
-npm-debug.log
-yarn-error.log
-testem.log
-/typings
-
-# System Files
-.DS_Store
-Thumbs.db
-
-*.tgz
diff --git a/apps/roadm/web/roadm-gui/BUILD.bazel b/apps/roadm/web/roadm-gui/BUILD.bazel
index 1dc27b3..dd6bd33 100644
--- a/apps/roadm/web/roadm-gui/BUILD.bazel
+++ b/apps/roadm/web/roadm-gui/BUILD.bazel
@@ -32,6 +32,7 @@
         "**/*.css",
         "**/*.html",
     ]),
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/apps/roadm/web/roadm-gui/lib/port/port.component.ts b/apps/roadm/web/roadm-gui/lib/port/port.component.ts
index 24913ab..51547b3 100644
--- a/apps/roadm/web/roadm-gui/lib/port/port.component.ts
+++ b/apps/roadm/web/roadm-gui/lib/port/port.component.ts
@@ -21,7 +21,7 @@
     WebSocketService,
     IconService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../web/gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { ActivatedRoute } from '@angular/router';
 import {FormGroup, FormControl} from '@angular/forms';
 
diff --git a/apps/roadm/web/roadm-gui/lib/roadm-gui-lib.module.ts b/apps/roadm/web/roadm-gui/lib/roadm-gui-lib.module.ts
index 7a75fde..e9f2d91 100644
--- a/apps/roadm/web/roadm-gui/lib/roadm-gui-lib.module.ts
+++ b/apps/roadm/web/roadm-gui/lib/roadm-gui-lib.module.ts
@@ -17,7 +17,7 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import {RouterModule} from '@angular/router';
-import { Gui2FwLibModule } from '../../../../../web/gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { RoadmDeviceComponent } from './roadm/roadm.component';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { RoadmPortComponent } from './port/port.component';
diff --git a/apps/roadm/web/roadm-gui/lib/roadm/roadm.component.disabled.spec.ts b/apps/roadm/web/roadm-gui/lib/roadm/roadm.component.disabled.spec.ts
index 63a51d1..43b4f9e 100644
--- a/apps/roadm/web/roadm-gui/lib/roadm/roadm.component.disabled.spec.ts
+++ b/apps/roadm/web/roadm-gui/lib/roadm/roadm.component.disabled.spec.ts
@@ -25,7 +25,7 @@
     IconService,
     LogService,
     Gui2FwLibModule,
-} from '../../../../../../web/gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
 import {FormsModule} from '@angular/forms';
 import {RouterTestingModule} from '@angular/router/testing';
diff --git a/apps/roadm/web/roadm-gui/lib/roadm/roadm.component.ts b/apps/roadm/web/roadm-gui/lib/roadm/roadm.component.ts
index 13e05dc..112dd1b 100644
--- a/apps/roadm/web/roadm-gui/lib/roadm/roadm.component.ts
+++ b/apps/roadm/web/roadm-gui/lib/roadm/roadm.component.ts
@@ -20,7 +20,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../web/gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 import { ActivatedRoute, Router } from '@angular/router';
 
diff --git a/web/gui2-fw-lib/.gitignore b/web/gui2-fw-lib/.gitignore
deleted file mode 100644
index 143aa64..0000000
--- a/web/gui2-fw-lib/.gitignore
+++ /dev/null
@@ -1,45 +0,0 @@
-# See http://help.github.com/ignore-files/ for more about ignoring files.
-
-# compiled output
-/dist
-/tmp
-/out-tsc
-/gui2-fw-lib-*.tgz
-
-# dependencies
-/node_modules
-
-# IDEs and editors
-/.idea
-.project
-.classpath
-.c9/
-*.launch
-.settings/
-*.sublime-workspace
-
-# IDE - VSCode
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-
-# misc
-/.sass-cache
-/connect.lock
-/coverage
-/libpeerconnection.log
-npm-debug.log
-yarn-error.log
-testem.log
-/typings
-
-# System Files
-.DS_Store
-Thumbs.db
-
-projects/gui2-fw-lib/src/assets
-
-.pki/
-.cache/
diff --git a/web/gui2-fw-lib/BUILD.bazel b/web/gui2-fw-lib/BUILD.bazel
index edf04f4..b333909 100644
--- a/web/gui2-fw-lib/BUILD.bazel
+++ b/web/gui2-fw-lib/BUILD.bazel
@@ -16,6 +16,7 @@
 
 load("@npm_angular_bazel//:index.bzl", "ng_module")
 load("@npm_bazel_typescript//:index.bzl", "ts_library")
+load("@npm_bazel_karma//:index.bzl", "karma_web_test_suite")
 
 package(default_visibility = ["//:__subpackages__"])
 
@@ -36,7 +37,6 @@
         ],
         exclude = [
             "**/*.spec.ts",
-            "test.ts",
         ],
     ),
     assets = glob([
@@ -48,6 +48,7 @@
     #    tsconfig = "tsconfig.json",
     generate_ve_shims = True,
     module_name = "gui2-fw-lib",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "@npm//@angular/animations",
         "@npm//@angular/common",
@@ -58,128 +59,53 @@
     ],
 )
 
-#filegroup(
-#    name = "rxjs_umd_modules",
-#    srcs = [
-#        # do not sort
-#        "@npm//:node_modules/rxjs/bundles/rxjs.umd.js",
-#        ":rxjs_shims.js",
-#    ],
-#)
-#
-#ts_library(
-#    name = "test_lib",
-#    testonly = 1,
-#    srcs = glob(["**/*.spec.ts"]),
-#    deps = [
-#        ":gui2-fw-lib",
-#        "@npm//@angular/common",
-#        "@npm//@angular/core",
-#        "@npm//@angular/platform-browser",
-#        "@npm//@angular/router",
-#        "@npm//@types",
-#        "@npm//rxjs",
-#    ],
-#)
-#
-#ts_library(
-#    name = "initialize_testbed",
-#    testonly = 1,
-#    srcs = [
-#        "initialize_testbed.ts",
-#    ],
-#    deps = [
-#        "@npm//@angular/core",
-#        "@npm//@angular/platform-browser-dynamic",
-#        "@npm//@types",
-#    ],
-#)
-#
-#ng_package(
-#    name = "gui2-fw-lib-pkg",
-#    srcs = [
-#        "package.json",
-#    ],
-#    data = glob(
-#        include = [
-#            "src/assets/**",
-#        ],
-#        exclude = [
-#            "**/*.spec.ts",
-#        ],
-#    ),
-#    entry_point = ":src/public-api.ts",  # In reality this is ignored and index.ts is used
-#    #    include_devmode_srcs = False,
-#    readme_md = "README.md",
-#    deps = [
-#        ":gui2-fw-lib",
-#        "@npm//@angular/animations",
-#        "@npm//@angular/common",
-#        "@npm//@angular/core",
-#        "@npm//@angular/platform-browser-dynamic",
-#        "@npm//@angular/router",
-#        "@npm//@types",
-#        "@npm//d3",
-#        "@npm//rxjs",
-#    ],
-#)
-#
-#genrule(
-#    name = "onos-gui2-fw-ng-build",
-#    srcs = [
-#        ":gui2-fw-lib-pkg",
-#    ],
-#    outs = [
-#        "gui2-fw-ng-build-prod.log",
-#        "gui2-fw-lib-ver.tgz",
-#    ],
-#    cmd = "ROOT=`pwd` &&" +
-#          " mkdir -p package &&" +
-#          " cp -r bazel-out/k8-fastbuild/bin/web/gui2-fw-lib/projects/gui2-fw-lib/gui2-fw-lib-pkg/* package &&" +
-#          " tar -czhf $$ROOT/$(location gui2-fw-lib-ver.tgz) package &&" +
-#          " touch $$ROOT/$(location gui2-fw-ng-build-prod.log)",  # to get the log always as the 2nd file
-#    message = "GUI FW Lib build",
-#    visibility = ["//visibility:public"],
-#)
-#
-#ts_web_test_suite(
-#    name = "gui2-fw-lib-test",
-#    srcs = [
-#        "@npm//:node_modules/tslib/tslib.js",
-#    ],
-#    # do not sort
-#    bootstrap = [
-#        "@npm//:node_modules/zone.js/dist/zone-testing-bundle.js",
-#        "@npm//:node_modules/reflect-metadata/Reflect.js",
-#    ],
-#    browsers = [
-#        "@io_bazel_rules_webtesting//browsers:chromium-local",
-#    ],
-#    runtime_deps = [
-#        ":initialize_testbed",
-#    ],
-#    deps = [
-#        ":rxjs_umd_modules",
-#        ":test_lib",
-#        "@npm//karma-jasmine",
-#    ],
-#)
-#
-#jdk_genrule(
-#    name = "gui2_fw_lib_ext_css",
-#    srcs = glob(
-#        [
-#            "src/lib/widget/panel.css",
-#            "src/lib/widget/panel-theme.css",
-#            "src/lib/widget/table.css",
-#            "src/lib/widget/table.theme.css",
-#            "src/lib/widget/table.theme.css",
-#            "src/lib/layer/loading.service.css",
-#        ],
-#    ),
-#    outs = ["gui2_fw_lib_css.jar"],
-#    cmd = " ROOT=`pwd` &&" +
-#          " cd web/gui2-fw-lib/projects/gui2-fw-lib/src/lib &&" +
-#          " jar Mcf $$ROOT/$@ .",
-#    visibility = ["//visibility:public"],
-#)
+ts_library(
+    name = "test_lib",
+    testonly = 1,
+    srcs = glob(
+        include = ["**/*.spec.ts"],
+        # TODO re-enable this test
+        exclude = ["lib/nav/nav.service.spec.ts"],
+    ),
+    tsconfig = "//web/gui2:tsconfig-test",
+    deps = [
+        ":gui2-fw-lib",
+        "@npm//@angular/common",
+        "@npm//@angular/core",
+        "@npm//@angular/forms",
+        "@npm//@angular/http",
+        "@npm//@angular/platform-browser",
+        "@npm//@angular/router",
+        "@npm//@types/jasmine",
+        "@npm//rxjs",
+    ],
+)
+
+karma_web_test_suite(
+    name = "test",
+    srcs = [
+        # We are manaully adding the bazel generated named-UMD d3 bundle here as
+        # named-UMD bundles for non-APF npm packages are not yet automatically added.
+        # This file is generated by the npm_umd_bundle @npm//d3
+        # rule that is setup by yarn_install.
+    ],
+    # do not sort
+    bootstrap = [
+        "@npm//:node_modules/zone.js/dist/zone-testing-bundle.js",
+        "@npm//:node_modules/reflect-metadata/Reflect.js",
+    ],
+    browsers = [
+        #        "@io_bazel_rules_webtesting//browsers:chromium-local",
+        "@io_bazel_rules_webtesting//browsers:firefox-local",
+    ],
+    tags = ["native"],
+    runtime_deps = [
+        "//web/gui2/src/main/webapp:initialize_testbed",
+    ],
+    deps = [
+        ":test_lib",
+        "//web/gui:src/main/webapp/data",
+        "//web/gui2/src/main/webapp:d3_requirejs",
+        "//web/gui2/src/main/webapp:rxjs_umd_modules",
+    ],
+)
diff --git a/web/gui2-fw-lib/lib/util/fn.service.ts b/web/gui2-fw-lib/lib/util/fn.service.ts
index 6694182..60d4950 100644
--- a/web/gui2-fw-lib/lib/util/fn.service.ts
+++ b/web/gui2-fw-lib/lib/util/fn.service.ts
@@ -139,55 +139,55 @@
      * properties to get these - and even then we have to filter
      * out the constructor and any member variables
      */
-    // areFunctions(api: Object, fnNames: string[]): boolean {
-    //     const fnLookup: Map<string, boolean> = new Map();
-    //     let extraFound: boolean = false;
-    //
-    //     if (!this.isA(fnNames)) {
-    //         return false;
-    //     }
-    //
-    //     const n: number = fnNames.length;
-    //     let i: number;
-    //     let name: string;
-    //
-    //     for (i = 0; i < n; i++) {
-    //         name = fnNames[i];
-    //         if (!this.isF(api[name])) {
-    //             return false;
-    //         }
-    //         fnLookup.set(name, true);
-    //     }
-    //
-    //     // check for properties on the API that are not listed in the array,
-    //     const keys = Object.getOwnPropertyNames(api);
-    //     if (keys.length === 0) {
-    //         return true;
-    //     }
-    //     // If the api is a class it will have a name,
-    //     //  else it will just be called 'Object'
-    //     const apiObjectName: string = api.constructor.name;
-    //     if (apiObjectName === 'Object') {
-    //         Object.keys(api).forEach((key) => {
-    //             if (!fnLookup.get(key)) {
-    //                 extraFound = true;
-    //             }
-    //         });
-    //     } else { // It is a class, so its functions will be in the child (prototype)
-    //         const pObj: Object = Object.getPrototypeOf(api);
-    //         for ( const key in Object.getOwnPropertyDescriptors(pObj) ) {
-    //             if (key === 'constructor') { // Filter out constructor
-    //                 continue;
-    //             }
-    //             const value = Object.getOwnPropertyDescriptor(pObj, key);
-    //             // Only compare functions. Look for any not given in the map
-    //             if (this.isF(value.value) && !fnLookup.get(key)) {
-    //                 extraFound = true;
-    //             }
-    //         }
-    //     }
-    //     return !extraFound;
-    // }
+    areFunctions(api: Object, fnNames: string[]): boolean {
+        const fnLookup: Map<string, boolean> = new Map();
+        let extraFound: boolean = false;
+
+        if (!this.isA(fnNames)) {
+            return false;
+        }
+
+        const n: number = fnNames.length;
+        let i: number;
+        let name: string;
+
+        for (i = 0; i < n; i++) {
+            name = fnNames[i];
+            if (!this.isF(api[name])) {
+                return false;
+            }
+            fnLookup.set(name, true);
+        }
+
+        // check for properties on the API that are not listed in the array,
+        const keys = Object.getOwnPropertyNames(api);
+        if (keys.length === 0) {
+            return true;
+        }
+        // If the api is a class it will have a name,
+        //  else it will just be called 'Object'
+        const apiObjectName: string = api.constructor.name;
+        if (apiObjectName === 'Object') {
+            Object.keys(api).forEach((key) => {
+                if (!fnLookup.get(key)) {
+                    extraFound = true;
+                }
+            });
+        } else { // It is a class, so its functions will be in the child (prototype)
+            const pObj: Object = Object.getPrototypeOf(api);
+            for ( const key in Object.getOwnPropertyDescriptors(pObj) ) {
+                if (key === 'constructor') { // Filter out constructor
+                    continue;
+                }
+                const value = Object.getOwnPropertyDescriptor(pObj, key);
+                // Only compare functions. Look for any not given in the map
+                if (this.isF(value.value) && !fnLookup.get(key)) {
+                    extraFound = true;
+                }
+            }
+        }
+        return !extraFound;
+    }
 
     /**
      * Returns true if all names in the array are defined as functions
diff --git a/web/gui2-fw-lib/patches/@angular+bazel+9.0.0-rc.7.patch b/web/gui2-fw-lib/patches/@angular+bazel+9.0.0-rc.7.patch
deleted file mode 100644
index 89fa345..0000000
--- a/web/gui2-fw-lib/patches/@angular+bazel+9.0.0-rc.7.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-diff --git a/node_modules/@angular/bazel/src/ng_package/ng_package.bzl b/node_modules/@angular/bazel/src/ng_package/ng_package.bzl
-index ccda5a5..00f1624 100755
---- a/node_modules/@angular/bazel/src/ng_package/ng_package.bzl
-+++ b/node_modules/@angular/bazel/src/ng_package/ng_package.bzl
-@@ -15,9 +15,9 @@ specification of this format at https://goo.gl/jB3GVv
- 
- load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSNamedModuleInfo", "NpmPackageInfo", "node_modules_aspect")
- load(
--    "@build_bazel_rules_nodejs//internal/npm_package:npm_package.bzl",
--    "NPM_PACKAGE_ATTRS",
--    "NPM_PACKAGE_OUTPUTS",
-+    "@build_bazel_rules_nodejs//internal/pkg_npm:pkg_npm.bzl",
-+    "PKG_NPM_ATTRS",
-+    "PKG_NPM_OUTPUTS",
-     "create_package",
- )
- load("//src:external.bzl", "FLAT_DTS_FILE_SUFFIX")
-@@ -619,7 +619,7 @@ def _ng_package_impl(ctx):
-             if JSNamedModuleInfo in dep:
-                 devfiles = depset(transitive = [devfiles, dep[JSNamedModuleInfo].sources])
- 
--    # Re-use the create_package function from the nodejs npm_package rule.
-+    # Re-use the create_package function from the nodejs pkg_npm rule.
-     package_dir = create_package(
-         ctx,
-         devfiles.to_list(),
-@@ -631,7 +631,7 @@ def _ng_package_impl(ctx):
- 
- _NG_PACKAGE_DEPS_ASPECTS = [esm5_outputs_aspect, ng_package_module_mappings_aspect, node_modules_aspect]
- 
--_NG_PACKAGE_ATTRS = dict(NPM_PACKAGE_ATTRS, **{
-+_NG_PACKAGE_ATTRS = dict(PKG_NPM_ATTRS, **{
-     "srcs": attr.label_list(
-         doc = """JavaScript source files from the workspace.
-         These can use ES2015 syntax and ES Modules (import/export)""",
-@@ -807,12 +807,12 @@ def _ng_package_outputs(name, entry_point, entry_point_name):
-         "umd": "%s.umd.js" % basename,
-         "umd_min": "%s.umd.min.js" % basename,
-     }
--    for key in NPM_PACKAGE_OUTPUTS:
--        # NPM_PACKAGE_OUTPUTS is a "normal" dict-valued outputs so it looks like
-+    for key in PKG_NPM_OUTPUTS:
-+        # PKG_NPM_OUTPUTS is a "normal" dict-valued outputs so it looks like
-         #  "pack": "%{name}.pack",
-         # But this is a function-valued outputs.
-         # Bazel won't replace the %{name} token so we have to do it.
--        outputs[key] = NPM_PACKAGE_OUTPUTS[key].replace("%{name}", name)
-+        outputs[key] = PKG_NPM_OUTPUTS[key].replace("%{name}", name)
-     return outputs
- 
- ng_package = rule(
diff --git a/web/gui2-fw-lib/test.ts b/web/gui2-fw-lib/test.ts
deleted file mode 100644
index af048c5e..0000000
--- a/web/gui2-fw-lib/test.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file is required by karma.conf.js and loads recursively all the .spec and framework files
-
-import 'core-js/es7/reflect';
-import 'zone.js/dist/zone';
-import 'zone.js/dist/zone-testing';
-import { getTestBed } from '@angular/core/testing';
-import {
-  BrowserDynamicTestingModule,
-  platformBrowserDynamicTesting
-} from '@angular/platform-browser-dynamic/testing';
-
-declare const require: any;
-
-// First, initialize the Angular testing environment.
-getTestBed().initTestEnvironment(
-  BrowserDynamicTestingModule,
-  platformBrowserDynamicTesting()
-);
-// Then we find all the tests.
-const context = require.context('./', true, /\.spec\.ts$/);
-// And load the modules.
-context.keys().map(context);
diff --git a/web/gui2-topo-lib/.gitignore b/web/gui2-topo-lib/.gitignore
deleted file mode 100644
index 03327b3..0000000
--- a/web/gui2-topo-lib/.gitignore
+++ /dev/null
@@ -1,48 +0,0 @@
-# See http://help.github.com/ignore-files/ for more about ignoring files.
-
-# compiled output
-/dist
-/tmp
-/out-tsc
-/gui2-topo-lib*.tgz
-
-# dependencies
-/node_modules
-
-# IDEs and editors
-/.idea
-.project
-.classpath
-.c9/
-*.launch
-.settings/
-*.sublime-workspace
-
-# IDE - VSCode
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-
-# misc
-/.sass-cache
-/connect.lock
-/coverage
-/libpeerconnection.log
-npm-debug.log
-yarn-error.log
-testem.log
-/typings
-
-# System Files
-.DS_Store
-Thumbs.db
-
-# Development only files
-/projects/gui2-topo-lib/fw
-/projects/gui2-topo-tester/src/data
-
-.cache/
-.npm/
-.pki/
diff --git a/web/gui2-topo-lib/BUILD.bazel b/web/gui2-topo-lib/BUILD.bazel
index 46ecb74..4e3275b 100644
--- a/web/gui2-topo-lib/BUILD.bazel
+++ b/web/gui2-topo-lib/BUILD.bazel
@@ -1,4 +1,6 @@
 load("@npm_angular_bazel//:index.bzl", "ng_module")
+load("@npm_bazel_typescript//:index.bzl", "ts_library")
+load("@npm_bazel_karma//:index.bzl", "karma_web_test_suite")
 
 package(default_visibility = ["//:__subpackages__"])
 
@@ -14,13 +16,13 @@
         include = ["**/*.ts"],
         exclude = [
             "**/*.spec.ts",
-            "test.ts",
         ],
     ),
     assets = glob([
         "**/*.css",
         "**/*.html",
     ]),
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = NG_FACTORY_ADDED_IMPORTS + [
         "//web/gui2-fw-lib",
         "@npm//@angular/core",
@@ -31,3 +33,144 @@
         "@npm//topojson-client",
     ],
 )
+
+ts_library(
+    name = "test_lib",
+    testonly = 1,
+    srcs = glob(
+        include = ["**/*.spec.ts"],
+        # TODO re-enable this test
+        exclude = [
+            "lib/layer/backgroundsvg/backgroundsvg.component.spec.ts",
+            "lib/layer/forcesvg/forcesvg.component.spec.ts",
+        ],
+    ),
+    tsconfig = "//web/gui2:tsconfig-test",
+    deps = [
+        ":gui2-topo-lib",
+        "//web/gui2-fw-lib",
+        "@npm//@angular/common",
+        "@npm//@angular/core",
+        "@npm//@angular/forms",
+        "@npm//@angular/http",
+        "@npm//@angular/platform-browser",
+        "@npm//@angular/router",
+        "@npm//@types/jasmine",
+        "@npm//rxjs",
+    ],
+)
+
+# Convert topojson-client to an AMD module so it can be loaded in the RequireJS test environment.
+genrule(
+    name = "topojson-client_requirejs",
+    srcs = [
+        "@npm//:node_modules/topojson-client/dist/topojson-client.js",
+    ],
+    outs = [
+        "topojson-client.js",
+    ],
+    cmd = """echo "define('topojson-client', function(require, exports, module) {" > $@ \
+             && cat $< >> $@ \
+             && echo '});' >> $@""",
+)
+
+# Convert d3-force to an AMD module so it can be loaded in the RequireJS test environment.
+genrule(
+    name = "d3-force_requirejs",
+    srcs = [
+        "@npm//:node_modules/d3-force/dist/d3-force.js",
+    ],
+    outs = [
+        "d3-force.js",
+    ],
+    cmd = """echo "define('d3-force', function(require, exports, module) {" > $@ \
+             && cat $< >> $@ \
+             && echo '});' >> $@""",
+)
+
+# Convert d3-quadtree to an AMD module so it can be loaded in the RequireJS test environment.
+genrule(
+    name = "d3-quadtree_requirejs",
+    srcs = [
+        "@npm//:node_modules/d3-quadtree/dist/d3-quadtree.js",
+    ],
+    outs = [
+        "d3-quadtree.js",
+    ],
+    cmd = """echo "define('d3-quadtree', function(require, exports, module) {" > $@ \
+             && cat $< >> $@ \
+             && echo '});' >> $@""",
+)
+
+# Convert d3-collection to an AMD module so it can be loaded in the RequireJS test environment.
+genrule(
+    name = "d3-collection_requirejs",
+    srcs = [
+        "@npm//:node_modules/d3-collection/dist/d3-collection.js",
+    ],
+    outs = [
+        "d3-collection.js",
+    ],
+    cmd = """echo "define('d3-collection', function(require, exports, module) {" > $@ \
+             && cat $< >> $@ \
+             && echo '});' >> $@""",
+)
+
+# Convert d3-dispatch to an AMD module so it can be loaded in the RequireJS test environment.
+genrule(
+    name = "d3-dispatch_requirejs",
+    srcs = [
+        "@npm//:node_modules/d3-dispatch/dist/d3-dispatch.js",
+    ],
+    outs = [
+        "d3-dispatch.js",
+    ],
+    cmd = """echo "define('d3-dispatch', function(require, exports, module) {" > $@ \
+             && cat $< >> $@ \
+             && echo '});' >> $@""",
+)
+
+# Convert d3-timer to an AMD module so it can be loaded in the RequireJS test environment.
+genrule(
+    name = "d3-timer_requirejs",
+    srcs = [
+        "@npm//:node_modules/d3-timer/dist/d3-timer.js",
+    ],
+    outs = [
+        "d3-timer.js",
+    ],
+    cmd = """echo "define('d3-timer', function(require, exports, module) {" > $@ \
+             && cat $< >> $@ \
+             && echo '});' >> $@""",
+)
+
+karma_web_test_suite(
+    name = "test",
+    srcs = [
+    ],
+    # do not sort
+    bootstrap = [
+        "@npm//:node_modules/zone.js/dist/zone-testing-bundle.js",
+        "@npm//:node_modules/reflect-metadata/Reflect.js",
+    ],
+    browsers = [
+        #        "@io_bazel_rules_webtesting//browsers:chromium-local",
+        "@io_bazel_rules_webtesting//browsers:firefox-local",
+    ],
+    tags = ["native"],
+    runtime_deps = [
+        "//web/gui2/src/main/webapp:initialize_testbed",
+    ],
+    deps = [
+        ":d3-collection_requirejs",
+        ":d3-dispatch_requirejs",
+        ":d3-force_requirejs",
+        ":d3-quadtree_requirejs",
+        ":d3-timer_requirejs",
+        ":test_lib",
+        ":topojson-client_requirejs",
+        "//web/gui:src/main/webapp/data",
+        "//web/gui2/src/main/webapp:d3_requirejs",
+        "//web/gui2/src/main/webapp:rxjs_umd_modules",
+    ],
+)
diff --git a/web/gui2-topo-lib/lib/gui2-topo-lib.module.ts b/web/gui2-topo-lib/lib/gui2-topo-lib.module.ts
index 26afcc3..70e2628 100644
--- a/web/gui2-topo-lib/lib/gui2-topo-lib.module.ts
+++ b/web/gui2-topo-lib/lib/gui2-topo-lib.module.ts
@@ -22,7 +22,7 @@
 import { SummaryComponent } from './panel/summary/summary.component';
 import { ToolbarComponent } from './panel/toolbar/toolbar.component';
 import { DetailsComponent } from './panel/details/details.component';
-import { Gui2FwLibModule } from '../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { BackgroundSvgComponent } from './layer/backgroundsvg/backgroundsvg.component';
 import { ForceSvgComponent } from './layer/forcesvg/forcesvg.component';
 import { MapSvgComponent } from './layer/mapsvg/mapsvg.component';
diff --git a/web/gui2-topo-lib/lib/layer/backgroundsvg/backgroundsvg.component.spec.ts b/web/gui2-topo-lib/lib/layer/backgroundsvg/backgroundsvg.component.spec.ts
index 1063017..1902505 100644
--- a/web/gui2-topo-lib/lib/layer/backgroundsvg/backgroundsvg.component.spec.ts
+++ b/web/gui2-topo-lib/lib/layer/backgroundsvg/backgroundsvg.component.spec.ts
@@ -19,7 +19,7 @@
 import {MapSvgComponent, TopoData} from '../mapsvg/mapsvg.component';
 import {from} from 'rxjs';
 import {HttpClient} from '@angular/common/http';
-import {LocMeta, LogService, ZoomUtils} from '../../../gui2-fw-lib/public_api';
+import {LocMeta, LogService, ZoomUtils} from 'gui2-fw-lib/public_api';
 import {MapObject} from '../maputils';
 import {ForceSvgComponent} from '../forcesvg/forcesvg.component';
 
diff --git a/web/gui2-topo-lib/lib/layer/backgroundsvg/backgroundsvg.component.ts b/web/gui2-topo-lib/lib/layer/backgroundsvg/backgroundsvg.component.ts
index 1af98d6..f985cad 100644
--- a/web/gui2-topo-lib/lib/layer/backgroundsvg/backgroundsvg.component.ts
+++ b/web/gui2-topo-lib/lib/layer/backgroundsvg/backgroundsvg.component.ts
@@ -15,7 +15,7 @@
  */
 import {Component, EventEmitter, Input, Output} from '@angular/core';
 import {MapObject} from '../maputils';
-import {MapBounds, TopoZoomPrefs, LogService, ZoomUtils} from '../../../../gui2-fw-lib/public_api';
+import {MapBounds, TopoZoomPrefs, LogService, ZoomUtils} from 'gui2-fw-lib/public_api';
 
 /**
  * model of the topo2CurrentLayout attrs from BgZoom below
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/draggable/draggable.directive.spec.ts b/web/gui2-topo-lib/lib/layer/forcesvg/draggable/draggable.directive.spec.ts
index bb7dfbf..a2015ef 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/draggable/draggable.directive.spec.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/draggable/draggable.directive.spec.ts
@@ -16,7 +16,7 @@
 import { DraggableDirective } from './draggable.directive';
 import {inject, TestBed} from '@angular/core/testing';
 import {ElementRef} from '@angular/core';
-import {LogService} from '../../../../../gui2-fw-lib/public_api';
+import {LogService} from 'gui2-fw-lib/public_api';
 
 export class MockElementRef extends ElementRef {
     nativeElement = {};
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/draggable/draggable.directive.ts b/web/gui2-topo-lib/lib/layer/forcesvg/draggable/draggable.directive.ts
index f476e46..c8c4643 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/draggable/draggable.directive.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/draggable/draggable.directive.ts
@@ -22,7 +22,7 @@
 } from '@angular/core';
 import {ForceDirectedGraph, Node} from '../models';
 import * as d3 from 'd3';
-import {LogService, MetaUi, ZoomUtils} from '../../../../../gui2-fw-lib/public_api';
+import {LogService, MetaUi, ZoomUtils} from 'gui2-fw-lib/public_api';
 import {BackgroundSvgComponent} from '../../backgroundsvg/backgroundsvg.component';
 
 @Directive({
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/forcesvg.component.spec.ts b/web/gui2-topo-lib/lib/layer/forcesvg/forcesvg.component.spec.ts
index 6ee354a..ce827e7 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/forcesvg.component.spec.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/forcesvg.component.spec.ts
@@ -22,7 +22,7 @@
     LogService, SvgUtilService,
     UrlFnService,
     WebSocketService
-} from '../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {DraggableDirective} from './draggable/draggable.directive';
 import {ActivatedRoute, Params} from '@angular/router';
 import {of} from 'rxjs';
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/forcesvg.component.ts b/web/gui2-topo-lib/lib/layer/forcesvg/forcesvg.component.ts
index ec3e57d..486bb86 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/forcesvg.component.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/forcesvg.component.ts
@@ -28,7 +28,7 @@
     SimpleChanges,
     ViewChildren
 } from '@angular/core';
-import {LocMeta, LogService, MetaUi, WebSocketService, ZoomUtils} from '../../../../gui2-fw-lib/public_api';
+import {LocMeta, LogService, MetaUi, WebSocketService, ZoomUtils} from 'gui2-fw-lib/public_api';
 import {
     Badge,
     Device, DeviceHighlight,
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/models/force-directed-graph.spec.ts b/web/gui2-topo-lib/lib/layer/forcesvg/models/force-directed-graph.spec.ts
index 2fb9155..876cab5 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/models/force-directed-graph.spec.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/models/force-directed-graph.spec.ts
@@ -16,7 +16,7 @@
 import {ForceDirectedGraph, Options} from './force-directed-graph';
 import {Node} from './node';
 import {Link} from './link';
-import {LogService} from '../../../../../gui2-fw-lib/public_api';
+import {LogService} from 'gui2-fw-lib/public_api';
 import {TestBed} from '@angular/core/testing';
 
 export class TestNode extends Node {
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/models/force-directed-graph.ts b/web/gui2-topo-lib/lib/layer/forcesvg/models/force-directed-graph.ts
index 7bf44af..2f316cb 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/models/force-directed-graph.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/models/force-directed-graph.ts
@@ -17,7 +17,7 @@
 import { Link } from './link';
 import { Node } from './node';
 import * as d3 from 'd3-force';
-import {LogService} from '../../../../../gui2-fw-lib/public_api';
+import {LogService} from 'gui2-fw-lib/public_api';
 
 const FORCES = {
     COLLISION: 1,
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/models/node.ts b/web/gui2-topo-lib/lib/layer/forcesvg/models/node.ts
index 5bcba8c..6a47ce3 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/models/node.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/models/node.ts
@@ -16,7 +16,7 @@
 import * as d3 from 'd3';
 import {LocationType} from '../../backgroundsvg/backgroundsvg.component';
 import {LayerType, Location, NodeType, RegionProps} from './regions';
-import {LocMeta, MetaUi, ZoomUtils} from '../../../../../gui2-fw-lib/public_api';
+import {LocMeta, MetaUi, ZoomUtils} from 'gui2-fw-lib/public_api';
 
 export interface UiElement {
     index?: number;
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.spec.ts b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.spec.ts
index deb175e..cd53c5f 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.spec.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.spec.ts
@@ -16,7 +16,7 @@
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 
 import { DeviceNodeSvgComponent } from './devicenodesvg.component';
-import {FnService, IconService, LogService, SvgUtilService} from '../../../../../../gui2-fw-lib/public_api';
+import {FnService, IconService, LogService, SvgUtilService} from 'gui2-fw-lib/public_api';
 import {ActivatedRoute, Params} from '@angular/router';
 import {of} from 'rxjs';
 import {ChangeDetectorRef} from '@angular/core';
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
index 2243e20..47791dd 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
@@ -27,7 +27,7 @@
     Device,
     LabelToggle,
 } from '../../models';
-import {IconService, LogService, SvgUtilService} from '../../../../../../gui2-fw-lib/public_api';
+import {IconService, LogService, SvgUtilService} from 'gui2-fw-lib/public_api';
 import {NodeVisual, SelectedEvent} from '../nodevisual';
 import {animate, state, style, transition, trigger} from '@angular/animations';
 import {TopologyService} from '../../../../topology.service';
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.spec.ts b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.spec.ts
index cf697bb..1929204 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.spec.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.spec.ts
@@ -18,7 +18,7 @@
 import { HostNodeSvgComponent } from './hostnodesvg.component';
 import {ActivatedRoute, Params} from '@angular/router';
 import {of} from 'rxjs';
-import {LogService} from '../../../../../../gui2-fw-lib/public_api';
+import {LogService} from 'gui2-fw-lib/public_api';
 import {Host} from '../../models';
 import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
 import {ChangeDetectorRef} from '@angular/core';
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
index decd099..e6febb6 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
@@ -22,7 +22,7 @@
     SimpleChanges
 } from '@angular/core';
 import {Badge, Host, HostLabelToggle, Node} from '../../models';
-import {LogService} from '../../../../../../gui2-fw-lib/public_api';
+import {LogService} from 'gui2-fw-lib/public_api';
 import {NodeVisual, SelectedEvent} from '../nodevisual';
 
 /**
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.spec.ts b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.spec.ts
index 6418fb4..11bc464 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.spec.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.spec.ts
@@ -16,7 +16,7 @@
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 
 import { LinkSvgComponent } from './linksvg.component';
-import {LogService} from '../../../../../../gui2-fw-lib/public_api';
+import {LogService} from 'gui2-fw-lib/public_api';
 import {ActivatedRoute, Params} from '@angular/router';
 import {of} from 'rxjs';
 import {Device, Link, RegionLink, LinkType} from '../../models';
diff --git a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
index 9997897..b691417 100644
--- a/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
+++ b/web/gui2-topo-lib/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
@@ -19,7 +19,7 @@
     Input, OnChanges, Output, SimpleChanges,
 } from '@angular/core';
 import {Link, LinkHighlight, UiElement} from '../../models';
-import {LogService} from '../../../../../../gui2-fw-lib/public_api';
+import {LogService} from 'gui2-fw-lib/public_api';
 import {NodeVisual, SelectedEvent} from '../nodevisual';
 import {animate, state, style, transition, trigger} from '@angular/animations';
 
diff --git a/web/gui2-topo-lib/lib/layer/mapsvg/mapsvg.component.spec.ts b/web/gui2-topo-lib/lib/layer/mapsvg/mapsvg.component.spec.ts
index 454aad0..b2cca6f 100644
--- a/web/gui2-topo-lib/lib/layer/mapsvg/mapsvg.component.spec.ts
+++ b/web/gui2-topo-lib/lib/layer/mapsvg/mapsvg.component.spec.ts
@@ -18,7 +18,7 @@
 import { MapSvgComponent } from './mapsvg.component';
 import {HttpClient} from '@angular/common/http';
 import {from} from 'rxjs';
-import {LogService} from '../../../gui2-fw-lib/public_api';
+import {LogService} from 'gui2-fw-lib/public_api';
 
 class MockHttpClient {
     get() {
diff --git a/web/gui2-topo-lib/lib/layer/mapsvg/mapsvg.component.ts b/web/gui2-topo-lib/lib/layer/mapsvg/mapsvg.component.ts
index 993aebf..28ece5e 100644
--- a/web/gui2-topo-lib/lib/layer/mapsvg/mapsvg.component.ts
+++ b/web/gui2-topo-lib/lib/layer/mapsvg/mapsvg.component.ts
@@ -20,7 +20,7 @@
     SimpleChanges
 } from '@angular/core';
 import { MapObject } from '../maputils';
-import {LogService, MapBounds} from '../../../../gui2-fw-lib/public_api';
+import {LogService, MapBounds} from 'gui2-fw-lib/public_api';
 import {HttpClient} from '@angular/common/http';
 import * as d3 from 'd3';
 import * as topojson from 'topojson-client';
diff --git a/web/gui2-topo-lib/lib/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.spec.ts b/web/gui2-topo-lib/lib/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.spec.ts
index 218f063..494bed5 100644
--- a/web/gui2-topo-lib/lib/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.spec.ts
+++ b/web/gui2-topo-lib/lib/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.spec.ts
@@ -27,7 +27,7 @@
     TableFilterPipe,
     IconComponent,
     WebSocketService, SvgUtilService, PrefsService
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { of } from 'rxjs';
 
 class MockActivatedRoute extends ActivatedRoute {
diff --git a/web/gui2-topo-lib/lib/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.ts b/web/gui2-topo-lib/lib/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.ts
index 84965fa..24e3af1 100644
--- a/web/gui2-topo-lib/lib/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.ts
+++ b/web/gui2-topo-lib/lib/layer/nodeviceconnectedsvg/nodeviceconnectedsvg.component.ts
@@ -27,7 +27,7 @@
     LogService,
     PrefsService,
     SvgUtilService, LionService, ZoomUtils, TopoZoomPrefs
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * ONOS GUI -- Topology No Connected Devices View.
diff --git a/web/gui2-topo-lib/lib/layer/viewcontroller.ts b/web/gui2-topo-lib/lib/layer/viewcontroller.ts
index e6568ed..8f4bac6 100644
--- a/web/gui2-topo-lib/lib/layer/viewcontroller.ts
+++ b/web/gui2-topo-lib/lib/layer/viewcontroller.ts
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { FnService, LogService, PrefsService } from '../../../gui2-fw-lib/public_api';
+import { FnService, LogService, PrefsService } from 'gui2-fw-lib/public_api';
 
 export interface ViewControllerPrefs {
     visible: string;
diff --git a/web/gui2-topo-lib/lib/layout.service.spec.ts b/web/gui2-topo-lib/lib/layout.service.spec.ts
index 2f8483f..943404e 100644
--- a/web/gui2-topo-lib/lib/layout.service.spec.ts
+++ b/web/gui2-topo-lib/lib/layout.service.spec.ts
@@ -18,7 +18,7 @@
 import { LayoutService } from './layout.service';
 import {ActivatedRoute, Params} from '@angular/router';
 import {of} from 'rxjs';
-import {FnService, LogService} from '../../gui2-fw-lib/public_api';
+import {FnService, LogService} from 'gui2-fw-lib/public_api';
 
 class MockActivatedRoute extends ActivatedRoute {
     constructor(params: Params) {
diff --git a/web/gui2-topo-lib/lib/layout.service.ts b/web/gui2-topo-lib/lib/layout.service.ts
index 39844c54..f3d5c52e 100644
--- a/web/gui2-topo-lib/lib/layout.service.ts
+++ b/web/gui2-topo-lib/lib/layout.service.ts
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 import { Injectable } from '@angular/core';
-import {LogService, WebSocketService} from '../../gui2-fw-lib/public_api';
+import {LogService, WebSocketService} from 'gui2-fw-lib/public_api';
 
 export enum LayoutType {
     LAYOUT_DEFAULT = 'default',
diff --git a/web/gui2-topo-lib/lib/panel/details/details.component.spec.ts b/web/gui2-topo-lib/lib/panel/details/details.component.spec.ts
index 0648c46..e1db5fd 100644
--- a/web/gui2-topo-lib/lib/panel/details/details.component.spec.ts
+++ b/web/gui2-topo-lib/lib/panel/details/details.component.spec.ts
@@ -22,7 +22,7 @@
 import {
     FnService, LionService,
     LogService, IconComponent
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {RouterTestingModule} from '@angular/router/testing';
 
 class MockActivatedRoute extends ActivatedRoute {
diff --git a/web/gui2-topo-lib/lib/panel/details/details.component.ts b/web/gui2-topo-lib/lib/panel/details/details.component.ts
index a0a2837..ce2116b 100644
--- a/web/gui2-topo-lib/lib/panel/details/details.component.ts
+++ b/web/gui2-topo-lib/lib/panel/details/details.component.ts
@@ -15,7 +15,7 @@
  */
 import {Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core';
 import {animate, state, style, transition, trigger} from '@angular/animations';
-import {DetailsPanelBaseImpl, FnService, LionService, LogService, WebSocketService} from '../../../../gui2-fw-lib/public_api';
+import {DetailsPanelBaseImpl, FnService, LionService, LogService, WebSocketService} from 'gui2-fw-lib/public_api';
 import {Host, Link, LinkType, NodeType, UiElement} from '../../layer/forcesvg/models';
 import {Params, Router} from '@angular/router';
 
diff --git a/web/gui2-topo-lib/lib/panel/instance/instance.component.spec.ts b/web/gui2-topo-lib/lib/panel/instance/instance.component.spec.ts
index 6b06753..b53adfe 100644
--- a/web/gui2-topo-lib/lib/panel/instance/instance.component.spec.ts
+++ b/web/gui2-topo-lib/lib/panel/instance/instance.component.spec.ts
@@ -22,7 +22,7 @@
 import {
     FnService,
     LogService
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 class MockActivatedRoute extends ActivatedRoute {
     constructor(params: Params) {
diff --git a/web/gui2-topo-lib/lib/panel/instance/instance.component.ts b/web/gui2-topo-lib/lib/panel/instance/instance.component.ts
index 53ecf12..4fe97ba 100644
--- a/web/gui2-topo-lib/lib/panel/instance/instance.component.ts
+++ b/web/gui2-topo-lib/lib/panel/instance/instance.component.ts
@@ -26,7 +26,7 @@
     PanelBaseImpl,
     IconService,
     SvgUtilService, LionService
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * A model of instance information that drives each panel
diff --git a/web/gui2-topo-lib/lib/panel/mapselector/mapselector.component.spec.ts b/web/gui2-topo-lib/lib/panel/mapselector/mapselector.component.spec.ts
index 3a30421..72caea7 100644
--- a/web/gui2-topo-lib/lib/panel/mapselector/mapselector.component.spec.ts
+++ b/web/gui2-topo-lib/lib/panel/mapselector/mapselector.component.spec.ts
@@ -19,7 +19,7 @@
 import {FormsModule, ReactiveFormsModule} from '@angular/forms';
 import {ActivatedRoute, Params} from '@angular/router';
 import {of} from 'rxjs';
-import {FnService, LogService} from '../../../../gui2-fw-lib/public_api';
+import {FnService, LogService} from 'gui2-fw-lib/public_api';
 
 class MockActivatedRoute extends ActivatedRoute {
     constructor(params: Params) {
diff --git a/web/gui2-topo-lib/lib/panel/mapselector/mapselector.component.ts b/web/gui2-topo-lib/lib/panel/mapselector/mapselector.component.ts
index e9cb56a..1b1b938 100644
--- a/web/gui2-topo-lib/lib/panel/mapselector/mapselector.component.ts
+++ b/web/gui2-topo-lib/lib/panel/mapselector/mapselector.component.ts
@@ -10,7 +10,7 @@
     LionService,
     LogService,
     WebSocketService
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {FormControl, FormGroup} from '@angular/forms';
 import { MapObject } from '../../layer/maputils';
 
diff --git a/web/gui2-topo-lib/lib/panel/summary/summary.component.spec.ts b/web/gui2-topo-lib/lib/panel/summary/summary.component.spec.ts
index 0a07d2e..e26ea2a 100644
--- a/web/gui2-topo-lib/lib/panel/summary/summary.component.spec.ts
+++ b/web/gui2-topo-lib/lib/panel/summary/summary.component.spec.ts
@@ -22,7 +22,7 @@
 import {
     FnService,
     LogService
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 class MockActivatedRoute extends ActivatedRoute {
     constructor(params: Params) {
diff --git a/web/gui2-topo-lib/lib/panel/summary/summary.component.ts b/web/gui2-topo-lib/lib/panel/summary/summary.component.ts
index 0191cd9..0eede5b 100644
--- a/web/gui2-topo-lib/lib/panel/summary/summary.component.ts
+++ b/web/gui2-topo-lib/lib/panel/summary/summary.component.ts
@@ -28,7 +28,7 @@
     FnService,
     WebSocketService,
     GlyphService
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 export interface SummaryResponse {
     title: string;
diff --git a/web/gui2-topo-lib/lib/panel/toolbar/toolbar.component.spec.ts b/web/gui2-topo-lib/lib/panel/toolbar/toolbar.component.spec.ts
index b1dff0b..79a4c6d 100644
--- a/web/gui2-topo-lib/lib/panel/toolbar/toolbar.component.spec.ts
+++ b/web/gui2-topo-lib/lib/panel/toolbar/toolbar.component.spec.ts
@@ -21,7 +21,7 @@
 import {
     FnService, LionService,
     LogService, IconComponent
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
 
 class MockActivatedRoute extends ActivatedRoute {
diff --git a/web/gui2-topo-lib/lib/panel/toolbar/toolbar.component.ts b/web/gui2-topo-lib/lib/panel/toolbar/toolbar.component.ts
index 725cbb1..d53720e 100644
--- a/web/gui2-topo-lib/lib/panel/toolbar/toolbar.component.ts
+++ b/web/gui2-topo-lib/lib/panel/toolbar/toolbar.component.ts
@@ -18,7 +18,7 @@
     LogService,
     FnService,
     PanelBaseImpl, LionService
-} from '../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 import {animate, state, style, transition, trigger} from '@angular/animations';
 
diff --git a/web/gui2-topo-lib/lib/panel/topopanel.base.ts b/web/gui2-topo-lib/lib/panel/topopanel.base.ts
index bea8f58..3915c24 100644
--- a/web/gui2-topo-lib/lib/panel/topopanel.base.ts
+++ b/web/gui2-topo-lib/lib/panel/topopanel.base.ts
@@ -17,7 +17,7 @@
     FnService,
     LogService,
     PanelBaseImpl
-} from '../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * Base model of panel view - implemented by Topology Panel components
diff --git a/web/gui2-topo-lib/lib/topology.service.spec.ts b/web/gui2-topo-lib/lib/topology.service.spec.ts
index a7c8463..72832de 100644
--- a/web/gui2-topo-lib/lib/topology.service.spec.ts
+++ b/web/gui2-topo-lib/lib/topology.service.spec.ts
@@ -21,7 +21,7 @@
 import {
     LogService,
     FnService
-} from '../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 class MockActivatedRoute extends ActivatedRoute {
     constructor(params: Params) {
diff --git a/web/gui2-topo-lib/lib/topology.service.ts b/web/gui2-topo-lib/lib/topology.service.ts
index 693a29a..c2beae7 100644
--- a/web/gui2-topo-lib/lib/topology.service.ts
+++ b/web/gui2-topo-lib/lib/topology.service.ts
@@ -16,7 +16,7 @@
 import {Injectable, SimpleChange} from '@angular/core';
 import {
     LogService, WebSocketService,
-} from '../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {Instance, InstanceComponent} from './panel/instance/instance.component';
 import { BackgroundSvgComponent } from './layer/backgroundsvg/backgroundsvg.component';
 import { ForceSvgComponent } from './layer/forcesvg/forcesvg.component';
diff --git a/web/gui2-topo-lib/lib/topology/topology.component.spec.ts b/web/gui2-topo-lib/lib/topology/topology.component.spec.ts
index 0ef9c5b..af96483 100644
--- a/web/gui2-topo-lib/lib/topology/topology.component.spec.ts
+++ b/web/gui2-topo-lib/lib/topology/topology.component.spec.ts
@@ -35,7 +35,7 @@
     FnService,
     LogService,
     IconService, IconComponent, PrefsService, KeysService, LionService, ZoomableDirective
-} from '../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {RouterTestingModule} from '@angular/router/testing';
 import {TrafficService} from '../traffic.service';
 import {ForceSvgComponent} from '../layer/forcesvg/forcesvg.component';
diff --git a/web/gui2-topo-lib/lib/topology/topology.component.ts b/web/gui2-topo-lib/lib/topology/topology.component.ts
index 601cfb1..0a3ae5a 100644
--- a/web/gui2-topo-lib/lib/topology/topology.component.ts
+++ b/web/gui2-topo-lib/lib/topology/topology.component.ts
@@ -33,7 +33,7 @@
     TopoZoomPrefs,
     WebSocketService,
     ZoomUtils
-} from '../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {InstanceComponent} from '../panel/instance/instance.component';
 import {DetailsComponent} from '../panel/details/details.component';
 import {BackgroundSvgComponent} from '../layer/backgroundsvg/backgroundsvg.component';
@@ -67,7 +67,7 @@
     ALARMS_TOGGLE
 } from '../panel/toolbar/toolbar.component';
 import {TrafficService, TrafficType} from '../traffic.service';
-import {ZoomableDirective} from '../../../gui2-fw-lib/public_api';
+import {ZoomableDirective} from 'gui2-fw-lib/public_api';
 import {MapObject} from '../layer/maputils';
 import {LayoutService, LayoutType} from '../layout.service';
 import {SelectedEvent} from '../layer/forcesvg/visuals/nodevisual';
diff --git a/web/gui2-topo-lib/lib/traffic.service.spec.ts b/web/gui2-topo-lib/lib/traffic.service.spec.ts
index 49ff94a..e15f8a5 100644
--- a/web/gui2-topo-lib/lib/traffic.service.spec.ts
+++ b/web/gui2-topo-lib/lib/traffic.service.spec.ts
@@ -16,7 +16,7 @@
 import { TestBed } from '@angular/core/testing';
 
 import { TrafficService } from './traffic.service';
-import {FnService, LogService} from '../../gui2-fw-lib/public_api';
+import {FnService, LogService} from 'gui2-fw-lib/public_api';
 import {ActivatedRoute, Params} from '@angular/router';
 import {of} from 'rxjs';
 
diff --git a/web/gui2-topo-lib/lib/traffic.service.ts b/web/gui2-topo-lib/lib/traffic.service.ts
index cd23209..8cc6070 100644
--- a/web/gui2-topo-lib/lib/traffic.service.ts
+++ b/web/gui2-topo-lib/lib/traffic.service.ts
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 import { Injectable } from '@angular/core';
-import {LogService, WebSocketService} from '../../gui2-fw-lib/public_api';
+import {LogService, WebSocketService} from 'gui2-fw-lib/public_api';
 import {ForceSvgComponent} from './layer/forcesvg/forcesvg.component';
 
 export namespace TrafficType {
diff --git a/web/gui2-topo-lib/test.ts b/web/gui2-topo-lib/test.ts
deleted file mode 100644
index f626203..0000000
--- a/web/gui2-topo-lib/test.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the 'License');
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file is required by karma.conf.js and loads recursively all the .spec and framework files
-
-import 'core-js/es7/reflect';
-import 'zone.js/dist/zone';
-import 'zone.js/dist/zone-testing';
-import { getTestBed } from '@angular/core/testing';
-import {
-  BrowserDynamicTestingModule,
-  platformBrowserDynamicTesting
-} from '@angular/platform-browser-dynamic/testing';
-
-declare const require: any;
-
-// First, initialize the Angular testing environment.
-getTestBed().initTestEnvironment(
-  BrowserDynamicTestingModule,
-  platformBrowserDynamicTesting()
-);
-// Then we find all the tests.
-const context = require.context('./', true, /\.spec\.ts$/);
-// And load the modules.
-context.keys().map(context);
diff --git a/web/gui2/.gitignore b/web/gui2/.gitignore
deleted file mode 100644
index e724aee..0000000
--- a/web/gui2/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-node_modules/
-documentation/
-dist/
-coverage/
-src/main/webapp/app/fw/
-
-.pki/
-.cache/
-.npm/
diff --git a/web/gui2/BUILD b/web/gui2/BUILD
index c3b700b..3fdc59d 100644
--- a/web/gui2/BUILD
+++ b/web/gui2/BUILD
@@ -19,6 +19,7 @@
 """
 
 load("//tools/build/bazel:jdk_genrule.bzl", genrule = "jdk_genrule")
+load("@npm_bazel_typescript//:index.bzl", "ts_config")
 
 COMPILE_DEPS = CORE_DEPS + JACKSON + KRYO + CLI + [
     "@javax_ws_rs_api//jar",
@@ -38,6 +39,20 @@
     "//drivers/default:onos-drivers-default",
 ]
 
+# This export allows targets in other packages to reference files that live
+# in this package.
+# TODO Try to move this in to /web/gui2-fw-lib when possible
+exports_files([
+    "tsconfig.json",
+])
+
+ts_config(
+    name = "tsconfig-test",
+    src = "tsconfig-test.json",
+    visibility = ["//visibility:public"],
+    deps = [":tsconfig.json"],
+)
+
 """
     Builds the java jar for the java code provided by the GUI2
 """
diff --git a/web/gui2/package.json b/web/gui2/package.json
index c262ca3..d60718b 100644
--- a/web/gui2/package.json
+++ b/web/gui2/package.json
@@ -11,6 +11,7 @@
         "@angular/common": "9.0.0-rc.7",
         "@angular/core": "9.0.0-rc.7",
         "@angular/forms": "9.0.0-rc.7",
+        "@angular/http": "^7.2.15",
         "@angular/platform-browser": "9.0.0-rc.7",
         "@angular/platform-browser-dynamic": "9.0.0-rc.7",
         "@angular/router": "9.0.0-rc.7",
@@ -26,25 +27,26 @@
         "@angular/compiler": "9.0.0-rc.7",
         "@angular/compiler-cli": "9.0.0-rc.7",
         "@bazel/hide-bazel-files": "1.0.0",
-        "@bazel/karma": "^1.0.0",
-        "@bazel/protractor": "^1.0.0",
-        "@bazel/typescript": "1.0.0",
-        "@bazel/rollup": "^1.0.0",
-        "@bazel/terser": "^1.0.0",
+        "@bazel/karma": "^1.0.1",
+        "@bazel/protractor": "^1.0.1",
+        "@bazel/typescript": "1.0.1",
+        "@bazel/rollup": "^1.0.1",
+        "@bazel/terser": "^1.0.1",
         "@compodoc/compodoc": "^1.1.3",
-        "@types/jasmine": "~3.3.8",
-        "@types/node": "~8.9.4",
+        "@types/jasmine": "~3.4.0",
+        "@types/node": "6.14.9",
         "core-js": "2.6.9",
         "history-server": "^1.3.1",
-        "jasmine-core": "~3.4.0",
-        "jasmine-spec-reporter": "~4.2.1",
+        "html-insert-assets": "^0.4.0",
         "karma": "~4.1.0",
         "karma-chrome-launcher": "~2.2.0",
-        "karma-coverage-istanbul-reporter": "~2.0.1",
         "karma-firefox-launcher": "^1.1.0",
         "karma-jasmine": "~2.0.1",
+        "karma-requirejs": "1.1.0",
+        "karma-sourcemap-loader": "0.3.7",
         "patch-package": "^6.2.0",
         "protractor": "~5.4.2",
+        "requirejs": "2.3.6",
         "rollup": "^1.21.4",
         "rollup-plugin-commonjs": "^10.1.0",
         "rollup-plugin-node-resolve": "^5.2.0",
diff --git a/web/gui2/patches/@angular+bazel+9.0.0-rc.7.patch b/web/gui2/patches/@angular+bazel+9.0.0-rc.7.patch
index 89fa345..f22e397 100644
--- a/web/gui2/patches/@angular+bazel+9.0.0-rc.7.patch
+++ b/web/gui2/patches/@angular+bazel+9.0.0-rc.7.patch
@@ -1,5 +1,5 @@
 diff --git a/node_modules/@angular/bazel/src/ng_package/ng_package.bzl b/node_modules/@angular/bazel/src/ng_package/ng_package.bzl
-index ccda5a5..00f1624 100755
+index 55bd685..3666382 100755
 --- a/node_modules/@angular/bazel/src/ng_package/ng_package.bzl
 +++ b/node_modules/@angular/bazel/src/ng_package/ng_package.bzl
 @@ -15,9 +15,9 @@ specification of this format at https://goo.gl/jB3GVv
diff --git a/web/gui2/src/main/webapp/BUILD.bazel b/web/gui2/src/main/webapp/BUILD.bazel
index 17eac76..966eb64 100644
--- a/web/gui2/src/main/webapp/BUILD.bazel
+++ b/web/gui2/src/main/webapp/BUILD.bazel
@@ -19,6 +19,7 @@
 load("@build_bazel_rules_nodejs//:index.bzl", "pkg_web")
 load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
 load("@npm//history-server:index.bzl", "history_server")
+load("@npm//html-insert-assets:index.bzl", "html_insert_assets")
 load("@npm_angular_bazel//:index.bzl", "ng_module")
 load("@npm_bazel_rollup//:index.bzl", "rollup_bundle")
 load("@npm_bazel_terser//:index.bzl", "terser_minified")
@@ -26,7 +27,9 @@
 
 #load("@npm_bazel_karma//:index.bzl", "ts_web_test_suite")
 
-exports_files(["WEB-INF/web.xml"])
+exports_files([
+    "WEB-INF/web.xml",
+])
 
 # We don't import from these, but the generated ngfactory code will
 NG_FACTORY_ADDED_IMPORTS = [
@@ -38,9 +41,10 @@
     name = "gui2",
     srcs = [
         "environments/environment.prod.ts",
+        "onos.dev.ts",
         "onos.prod.ts",
     ],
-    tsconfig = "//:tsconfig.json",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = NG_FACTORY_ADDED_IMPORTS + [
         "//web/gui2/src/main/webapp/app:app",
         "@npm//@angular/core",
@@ -98,7 +102,7 @@
         # Include polyfills that will be requested by old browsers
         #        "@npm//:node_modules/systemjs/dist/system.js",
         #        "@npm//:node_modules/core-js/client/core.min.js",
-        "index.html",
+        ":index.html",
     ],
     # In production mode we serve some polyfills with script tags that have hard-coded paths in the index.html
     # so we must serve them at that path, by stripping a prefix
@@ -120,10 +124,38 @@
     ],
 )
 
+filegroup(
+    name = "rxjs_umd_modules",
+    srcs = [
+        ":rxjs_shims.js",
+        "@npm//:node_modules/rxjs/bundles/rxjs.umd.js",
+    ],
+)
+
+# Convert d3 to an AMD module so it can be loaded in the RequireJS test environment.
 genrule(
-    name = "d3-copy",
-    srcs = ["@npm//:node_modules/d3/dist/d3.js"],
-    outs = ["d3.js"],
-    cmd = "cp $< $@",
-    output_to_bindir = 1,
+    name = "d3_requirejs",
+    srcs = [
+        "@npm//:node_modules/d3/dist/d3.js",
+    ],
+    outs = [
+        "d3.js",
+    ],
+    cmd = """echo "define('d3', function(require, exports, module) {" > $@ \
+             && cat $< >> $@ \
+             && echo '});' >> $@""",
+)
+
+ts_library(
+    name = "initialize_testbed",
+    testonly = 1,
+    srcs = [
+        "initialize_testbed.ts",
+    ],
+    tsconfig = "//web/gui2:tsconfig.json",
+    deps = [
+        "@npm//@angular/core",
+        "@npm//@angular/platform-browser-dynamic",
+        "@npm//@types",
+    ],
 )
diff --git a/web/gui2/src/main/webapp/app/BUILD.bazel b/web/gui2/src/main/webapp/app/BUILD.bazel
index 38cb9ae..26bd005 100644
--- a/web/gui2/src/main/webapp/app/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/BUILD.bazel
@@ -15,6 +15,8 @@
 """
 
 load("@npm_angular_bazel//:index.bzl", "ng_module")
+load("@npm_bazel_karma//:index.bzl", "karma_web_test_suite")
+load("@npm_bazel_typescript//:index.bzl", "ts_library")
 
 package(default_visibility = ["//:__subpackages__"])
 
@@ -41,7 +43,7 @@
         "nav/nav.component.html",
         "nav/nav.theme.css",
     ],
-    tsconfig = "//:tsconfig.json",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = NG_FACTORY_ADDED_IMPORTS + [
         "//web/gui2-fw-lib",
         "//web/gui2/src/main/webapp/app/view/apps:gui2-view-apps",
diff --git a/web/gui2/src/main/webapp/app/nav/nav.component.spec.ts b/web/gui2/src/main/webapp/app/nav/nav.component.spec.ts
index 7b3fbfa..126d4e2 100644
--- a/web/gui2/src/main/webapp/app/nav/nav.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/nav/nav.component.spec.ts
@@ -28,7 +28,7 @@
     IconService,
     LionService,
     LogService,
-    NavService } from 'gui2-fw-lib';
+    NavService } from 'gui2-fw-lib/public_api';
 import { NavComponent } from './nav.component';
 
 class MockActivatedRoute extends ActivatedRoute {
diff --git a/web/gui2/src/main/webapp/app/nav/nav.component.ts b/web/gui2/src/main/webapp/app/nav/nav.component.ts
index 567b6c5..95808b2 100644
--- a/web/gui2/src/main/webapp/app/nav/nav.component.ts
+++ b/web/gui2/src/main/webapp/app/nav/nav.component.ts
@@ -19,8 +19,8 @@
 import {
     LionService,
     LogService,
-    NavService
-} from '../../../../../../gui2-fw-lib/public_api';
+    NavService,
+} from 'gui2-fw-lib/public_api';
 
 /**
  * ONOS GUI -- Navigation Module
diff --git a/web/gui2/src/main/webapp/app/onos.component.spec.ts b/web/gui2/src/main/webapp/app/onos.component.spec.ts
index 0801494..4937618 100644
--- a/web/gui2/src/main/webapp/app/onos.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/onos.component.spec.ts
@@ -40,7 +40,7 @@
     ThemeService,
     WebSocketService,
     WsOptions
-} from 'gui2-fw-lib';
+} from 'gui2-fw-lib/public_api';
 
 class MockActivatedRoute extends ActivatedRoute {
     constructor(params: Params) {
diff --git a/web/gui2/src/main/webapp/app/onos.component.ts b/web/gui2/src/main/webapp/app/onos.component.ts
index 4b27a3e..f12593d 100644
--- a/web/gui2/src/main/webapp/app/onos.component.ts
+++ b/web/gui2/src/main/webapp/app/onos.component.ts
@@ -24,7 +24,7 @@
     WebSocketService,
     WsOptions,
     KeysService
-} from '../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { OnosService, View } from './onos.service';
 
 // secret sauce
diff --git a/web/gui2/src/main/webapp/app/onos.module.ts b/web/gui2/src/main/webapp/app/onos.module.ts
index 0e8b9ba..f7b1a3c 100644
--- a/web/gui2/src/main/webapp/app/onos.module.ts
+++ b/web/gui2/src/main/webapp/app/onos.module.ts
@@ -25,7 +25,7 @@
     Gui2FwLibModule,
     ConsoleLoggerService,
     LogService
-} from '../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { OnosService } from './onos.service';
 
 /**
diff --git a/web/gui2/src/main/webapp/app/onos.service.spec.ts b/web/gui2/src/main/webapp/app/onos.service.spec.ts
index c9dfdb3..26e7193 100644
--- a/web/gui2/src/main/webapp/app/onos.service.spec.ts
+++ b/web/gui2/src/main/webapp/app/onos.service.spec.ts
@@ -15,7 +15,7 @@
  */
 import { TestBed, inject } from '@angular/core/testing';
 
-import { LogService, ConsoleLoggerService } from 'gui2-fw-lib';
+import { LogService, ConsoleLoggerService } from 'gui2-fw-lib/public_api';
 import { OnosService } from './onos.service';
 
 /**
diff --git a/web/gui2/src/main/webapp/app/onos.service.ts b/web/gui2/src/main/webapp/app/onos.service.ts
index c64267e..ef34c22 100644
--- a/web/gui2/src/main/webapp/app/onos.service.ts
+++ b/web/gui2/src/main/webapp/app/onos.service.ts
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 import {Inject, Injectable} from '@angular/core';
-import { LogService } from '../../../../../gui2-fw-lib/public_api';
+import { LogService } from 'gui2-fw-lib/public_api';
 
 /**
  * A structure of View elements for the OnosService
diff --git a/web/gui2/src/main/webapp/app/view/apps/BUILD.bazel b/web/gui2/src/main/webapp/app/view/apps/BUILD.bazel
index 472a086..9cfeb2a 100644
--- a/web/gui2/src/main/webapp/app/view/apps/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/apps/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-apps",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps.module.ts b/web/gui2/src/main/webapp/app/view/apps/apps.module.ts
index 76215e5..cc34c58 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps.module.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/apps.module.ts
@@ -19,7 +19,7 @@
 import { RouterModule } from '@angular/router';
 import { AppsComponent } from './apps/apps.component';
 import { AppsDetailsComponent } from './appsdetails/appsdetails.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 
 /**
  * ONOS GUI -- Apps View Module
@@ -32,7 +32,6 @@
     imports: [
         CommonModule,
         Gui2FwLibModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: AppsComponent}]),
         FormsModule
     ],
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.ts b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.ts
index e76bf64..7760d22 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/apps/apps.component.ts
@@ -24,7 +24,7 @@
     TableBaseImpl, TableResponse, SortDir,
     UrlFnService,
     WebSocketService
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 const INSTALLED = 'INSTALLED';
 const ACTIVE = 'ACTIVE';
diff --git a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.ts b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.ts
index b3bbdb8..bee217b 100644
--- a/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/appsdetails/appsdetails.component.ts
@@ -21,7 +21,7 @@
     LogService,
     DetailsPanelBaseImpl,
     WebSocketService
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 import { App, APPURLPREFIX, ICONURLSUFFIX } from '../apps/apps.component';
 
diff --git a/web/gui2/src/main/webapp/app/view/cluster/BUILD.bazel b/web/gui2/src/main/webapp/app/view/cluster/BUILD.bazel
index 5401cad..3dc548e 100644
--- a/web/gui2/src/main/webapp/app/view/cluster/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/cluster/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-cluster",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/cluster/cluster-details.directive.ts b/web/gui2/src/main/webapp/app/view/cluster/cluster-details.directive.ts
index 4ddcb02..7363788 100644
--- a/web/gui2/src/main/webapp/app/view/cluster/cluster-details.directive.ts
+++ b/web/gui2/src/main/webapp/app/view/cluster/cluster-details.directive.ts
@@ -23,7 +23,7 @@
     LionService,
     PanelService,
     WebSocketService
-} from '../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import * as d3 from 'd3';
 import {HostListener} from '@angular/core';
 
diff --git a/web/gui2/src/main/webapp/app/view/cluster/cluster.module.ts b/web/gui2/src/main/webapp/app/view/cluster/cluster.module.ts
index 50db1da..adf7d41 100644
--- a/web/gui2/src/main/webapp/app/view/cluster/cluster.module.ts
+++ b/web/gui2/src/main/webapp/app/view/cluster/cluster.module.ts
@@ -15,7 +15,7 @@
  */
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { ClusterComponent } from './cluster/cluster.component';
 import { ClusterDetailsDirective } from './cluster-details.directive';
 import {RouterModule} from '@angular/router';
@@ -24,7 +24,6 @@
     imports: [
         CommonModule,
         Gui2FwLibModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: ClusterComponent}]),
     ],
     declarations: [ClusterComponent, ClusterDetailsDirective]
diff --git a/web/gui2/src/main/webapp/app/view/cluster/cluster/cluster.component.ts b/web/gui2/src/main/webapp/app/view/cluster/cluster/cluster.component.ts
index a4d43b1..9b42c12 100644
--- a/web/gui2/src/main/webapp/app/view/cluster/cluster/cluster.component.ts
+++ b/web/gui2/src/main/webapp/app/view/cluster/cluster/cluster.component.ts
@@ -20,7 +20,7 @@
     WebSocketService,
     LionService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * Model of the response from WebSocket
diff --git a/web/gui2/src/main/webapp/app/view/device/BUILD.bazel b/web/gui2/src/main/webapp/app/view/device/BUILD.bazel
index ac3eb0c..f821a4f 100644
--- a/web/gui2/src/main/webapp/app/view/device/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/device/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-device",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/device/device.module.ts b/web/gui2/src/main/webapp/app/view/device/device.module.ts
index a038ef5..535b8bb 100644
--- a/web/gui2/src/main/webapp/app/view/device/device.module.ts
+++ b/web/gui2/src/main/webapp/app/view/device/device.module.ts
@@ -15,9 +15,9 @@
  */
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import { Routes, RouterModule } from '@angular/router';
+import { RouterModule } from '@angular/router';
 import { DeviceComponent } from './device/device.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { FormsModule } from '@angular/forms';
 import { DeviceDetailsComponent } from './devicedetails/devicedetails.component';
 
@@ -27,7 +27,6 @@
 @NgModule({
     imports: [
         CommonModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: DeviceComponent}]),
         Gui2FwLibModule,
         FormsModule
diff --git a/web/gui2/src/main/webapp/app/view/device/device/device.component.ts b/web/gui2/src/main/webapp/app/view/device/device/device.component.ts
index 22322a6..c81f072 100644
--- a/web/gui2/src/main/webapp/app/view/device/device/device.component.ts
+++ b/web/gui2/src/main/webapp/app/view/device/device/device.component.ts
@@ -20,7 +20,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 import { ActivatedRoute, Router } from '@angular/router';
 
diff --git a/web/gui2/src/main/webapp/app/view/device/devicedetails/devicedetails.component.ts b/web/gui2/src/main/webapp/app/view/device/devicedetails/devicedetails.component.ts
index 439c302..e0819bb 100644
--- a/web/gui2/src/main/webapp/app/view/device/devicedetails/devicedetails.component.ts
+++ b/web/gui2/src/main/webapp/app/view/device/devicedetails/devicedetails.component.ts
@@ -21,7 +21,7 @@
     LogService,
     DetailsPanelBaseImpl,
     WebSocketService
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * The details view when a device row is clicked from the Device view
diff --git a/web/gui2/src/main/webapp/app/view/flow/BUILD.bazel b/web/gui2/src/main/webapp/app/view/flow/BUILD.bazel
index 7c5bbf7..fe80c74 100644
--- a/web/gui2/src/main/webapp/app/view/flow/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/flow/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-flow",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/flow/flow.module.ts b/web/gui2/src/main/webapp/app/view/flow/flow.module.ts
index c51da09..19f7720 100644
--- a/web/gui2/src/main/webapp/app/view/flow/flow.module.ts
+++ b/web/gui2/src/main/webapp/app/view/flow/flow.module.ts
@@ -16,7 +16,7 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FlowComponent } from './flow/flow.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { FormsModule } from '@angular/forms';
 import { FlowDetailsComponent } from './flowdetails/flowdetails/flowdetails.component';
 import {RouterModule} from '@angular/router';
@@ -28,7 +28,6 @@
     imports: [
         CommonModule,
         Gui2FwLibModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: FlowComponent}]),
         FormsModule
     ],
diff --git a/web/gui2/src/main/webapp/app/view/flow/flow/flow.component.ts b/web/gui2/src/main/webapp/app/view/flow/flow/flow.component.ts
index 8c81bb3..84790db 100644
--- a/web/gui2/src/main/webapp/app/view/flow/flow/flow.component.ts
+++ b/web/gui2/src/main/webapp/app/view/flow/flow/flow.component.ts
@@ -21,7 +21,7 @@
     WebSocketService,
     LionService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { ActivatedRoute } from '@angular/router';
 
 /**
diff --git a/web/gui2/src/main/webapp/app/view/flow/flowdetails/flowdetails/flowdetails.component.ts b/web/gui2/src/main/webapp/app/view/flow/flowdetails/flowdetails/flowdetails.component.ts
index f9b3f4c..180bac9 100644
--- a/web/gui2/src/main/webapp/app/view/flow/flowdetails/flowdetails/flowdetails.component.ts
+++ b/web/gui2/src/main/webapp/app/view/flow/flowdetails/flowdetails/flowdetails.component.ts
@@ -20,7 +20,7 @@
     LogService,
     DetailsPanelBaseImpl,
     WebSocketService
-} from '../../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { trigger, state, style, transition, animate } from '@angular/animations';
 
 /**
diff --git a/web/gui2/src/main/webapp/app/view/group/BUILD.bazel b/web/gui2/src/main/webapp/app/view/group/BUILD.bazel
index 82ad14a..5eb3695 100644
--- a/web/gui2/src/main/webapp/app/view/group/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/group/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-group",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/group/group.module.ts b/web/gui2/src/main/webapp/app/view/group/group.module.ts
index 9ffee40..b7000db 100644
--- a/web/gui2/src/main/webapp/app/view/group/group.module.ts
+++ b/web/gui2/src/main/webapp/app/view/group/group.module.ts
@@ -16,14 +16,13 @@
 import {NgModule} from '@angular/core';
 import {CommonModule} from '@angular/common';
 import {GroupComponent} from './group/group.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import {FormsModule} from '@angular/forms';
 import {RouterModule} from '@angular/router';
 
 @NgModule({
     imports: [
         CommonModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: GroupComponent}]),
         Gui2FwLibModule,
         FormsModule,
diff --git a/web/gui2/src/main/webapp/app/view/group/group/group.component.ts b/web/gui2/src/main/webapp/app/view/group/group/group.component.ts
index fbb58ba..8d7b9f8 100644
--- a/web/gui2/src/main/webapp/app/view/group/group/group.component.ts
+++ b/web/gui2/src/main/webapp/app/view/group/group/group.component.ts
@@ -19,7 +19,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { ActivatedRoute } from '@angular/router';
 
 /**
diff --git a/web/gui2/src/main/webapp/app/view/host/BUILD.bazel b/web/gui2/src/main/webapp/app/view/host/BUILD.bazel
index 78f486f..df3f9be 100644
--- a/web/gui2/src/main/webapp/app/view/host/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/host/BUILD.bazel
@@ -32,7 +32,7 @@
         "**/*.css",
         "**/*.html",
     ]),
-    module_name = "gui2-view-host",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/host/host.module.ts b/web/gui2/src/main/webapp/app/view/host/host.module.ts
index 1873fce..33ad589 100644
--- a/web/gui2/src/main/webapp/app/view/host/host.module.ts
+++ b/web/gui2/src/main/webapp/app/view/host/host.module.ts
@@ -17,14 +17,13 @@
 import { CommonModule } from '@angular/common';
 
 import { HostComponent } from './host/host.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { HostDetailsComponent } from './hostdetails/hostdetails.component';
 import {RouterModule} from '@angular/router';
 
 @NgModule({
     imports: [
         CommonModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: HostComponent}]),
         Gui2FwLibModule
     ],
diff --git a/web/gui2/src/main/webapp/app/view/host/host/host.component.ts b/web/gui2/src/main/webapp/app/view/host/host/host.component.ts
index 22c0e58..f2ddaf5 100644
--- a/web/gui2/src/main/webapp/app/view/host/host/host.component.ts
+++ b/web/gui2/src/main/webapp/app/view/host/host/host.component.ts
@@ -19,7 +19,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 interface HostTableResponse extends TableResponse {
     hosts: Host[];
diff --git a/web/gui2/src/main/webapp/app/view/host/hostdetails/hostdetails.component.ts b/web/gui2/src/main/webapp/app/view/host/hostdetails/hostdetails.component.ts
index 50af4f6..945f723 100644
--- a/web/gui2/src/main/webapp/app/view/host/hostdetails/hostdetails.component.ts
+++ b/web/gui2/src/main/webapp/app/view/host/hostdetails/hostdetails.component.ts
@@ -21,7 +21,7 @@
     LogService,
     DetailsPanelBaseImpl,
     WebSocketService
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * The details view when a host row is clicked from the Host view
diff --git a/web/gui2/src/main/webapp/app/view/intent/BUILD.bazel b/web/gui2/src/main/webapp/app/view/intent/BUILD.bazel
index 81739e5..e8c5508 100644
--- a/web/gui2/src/main/webapp/app/view/intent/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/intent/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-intent",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/intent/intent.module.ts b/web/gui2/src/main/webapp/app/view/intent/intent.module.ts
index 49869ee..22fb932 100644
--- a/web/gui2/src/main/webapp/app/view/intent/intent.module.ts
+++ b/web/gui2/src/main/webapp/app/view/intent/intent.module.ts
@@ -17,14 +17,13 @@
 import { CommonModule } from '@angular/common';
 
 import { IntentComponent } from './intent/intent.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { RouterModule } from '@angular/router';
 
 @NgModule({
     imports: [
         CommonModule,
         Gui2FwLibModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: IntentComponent}]),
     ],
     declarations: [IntentComponent],
diff --git a/web/gui2/src/main/webapp/app/view/intent/intent/intent.component.ts b/web/gui2/src/main/webapp/app/view/intent/intent/intent.component.ts
index 0e9fc449..b45f652 100644
--- a/web/gui2/src/main/webapp/app/view/intent/intent/intent.component.ts
+++ b/web/gui2/src/main/webapp/app/view/intent/intent/intent.component.ts
@@ -19,7 +19,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 const RESUBMITINTENT = 'resubmitIntent';
 const REMOVEINTENT = 'removeIntent';
diff --git a/web/gui2/src/main/webapp/app/view/link/BUILD.bazel b/web/gui2/src/main/webapp/app/view/link/BUILD.bazel
index 5625ec4..f7c458d 100644
--- a/web/gui2/src/main/webapp/app/view/link/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/link/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-link",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/link/link.module.ts b/web/gui2/src/main/webapp/app/view/link/link.module.ts
index 383e881..4c1e020 100644
--- a/web/gui2/src/main/webapp/app/view/link/link.module.ts
+++ b/web/gui2/src/main/webapp/app/view/link/link.module.ts
@@ -16,13 +16,12 @@
 import {NgModule} from '@angular/core';
 import {CommonModule} from '@angular/common';
 import {LinkComponent} from './link/link.component';
-import {Gui2FwLibModule} from '../../../../../../../gui2-fw-lib/public_api';
+import {Gui2FwLibModule} from 'gui2-fw-lib/public_api';
 import {RouterModule} from '@angular/router';
 
 @NgModule({
     imports: [
         CommonModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: LinkComponent}]),
         Gui2FwLibModule
     ],
diff --git a/web/gui2/src/main/webapp/app/view/link/link/link.component.ts b/web/gui2/src/main/webapp/app/view/link/link/link.component.ts
index d59ac18..90c0e64 100644
--- a/web/gui2/src/main/webapp/app/view/link/link/link.component.ts
+++ b/web/gui2/src/main/webapp/app/view/link/link/link.component.ts
@@ -19,7 +19,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * Model of the response from WebSocket
diff --git a/web/gui2/src/main/webapp/app/view/meter/BUILD.bazel b/web/gui2/src/main/webapp/app/view/meter/BUILD.bazel
index b4607f3..01f2f95 100644
--- a/web/gui2/src/main/webapp/app/view/meter/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/meter/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-meter",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/meter/meter.module.ts b/web/gui2/src/main/webapp/app/view/meter/meter.module.ts
index d5244c9..5bebc19 100644
--- a/web/gui2/src/main/webapp/app/view/meter/meter.module.ts
+++ b/web/gui2/src/main/webapp/app/view/meter/meter.module.ts
@@ -15,7 +15,7 @@
 */
 import {NgModule} from '@angular/core';
 import {CommonModule} from '@angular/common';
-import {Gui2FwLibModule} from '../../../../../../../gui2-fw-lib/public_api';
+import {Gui2FwLibModule} from 'gui2-fw-lib/public_api';
 import {MeterComponent} from './meter/meter.component';
 import {FormsModule} from '@angular/forms';
 import {RouterModule} from '@angular/router';
@@ -24,7 +24,6 @@
     imports: [
         CommonModule,
         Gui2FwLibModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: MeterComponent}]),
         FormsModule
     ],
diff --git a/web/gui2/src/main/webapp/app/view/meter/meter/meter.component.ts b/web/gui2/src/main/webapp/app/view/meter/meter/meter.component.ts
index 62501bf..8d9f0b0 100644
--- a/web/gui2/src/main/webapp/app/view/meter/meter/meter.component.ts
+++ b/web/gui2/src/main/webapp/app/view/meter/meter/meter.component.ts
@@ -19,7 +19,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { ActivatedRoute } from '@angular/router';
 
 /**
diff --git a/web/gui2/src/main/webapp/app/view/partition/BUILD.bazel b/web/gui2/src/main/webapp/app/view/partition/BUILD.bazel
index 7c86a08..80cbe05 100644
--- a/web/gui2/src/main/webapp/app/view/partition/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/partition/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-partition",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/partition/partition.module.ts b/web/gui2/src/main/webapp/app/view/partition/partition.module.ts
index 0f3c852..e7b8069 100644
--- a/web/gui2/src/main/webapp/app/view/partition/partition.module.ts
+++ b/web/gui2/src/main/webapp/app/view/partition/partition.module.ts
@@ -15,7 +15,7 @@
  */
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import {Gui2FwLibModule} from '../../../../../../../gui2-fw-lib/public_api';
+import {Gui2FwLibModule} from 'gui2-fw-lib/public_api';
 
 import { PartitionComponent } from './partition/partition.component';
 import {RouterModule} from '@angular/router';
@@ -24,7 +24,6 @@
     imports: [
         CommonModule,
         Gui2FwLibModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: PartitionComponent}]),
     ],
     declarations: [PartitionComponent]
diff --git a/web/gui2/src/main/webapp/app/view/partition/partition/partition.component.ts b/web/gui2/src/main/webapp/app/view/partition/partition/partition.component.ts
index dd2a509..0bf87d0 100644
--- a/web/gui2/src/main/webapp/app/view/partition/partition/partition.component.ts
+++ b/web/gui2/src/main/webapp/app/view/partition/partition/partition.component.ts
@@ -19,7 +19,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { ActivatedRoute } from '@angular/router';
 
 /**
diff --git a/web/gui2/src/main/webapp/app/view/pipeconf/BUILD.bazel b/web/gui2/src/main/webapp/app/view/pipeconf/BUILD.bazel
index ecd43ea..16250bb 100644
--- a/web/gui2/src/main/webapp/app/view/pipeconf/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/pipeconf/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-pipeconf",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/pipeconf/pipeconf.module.ts b/web/gui2/src/main/webapp/app/view/pipeconf/pipeconf.module.ts
index f2481f9..3e0c5c6 100644
--- a/web/gui2/src/main/webapp/app/view/pipeconf/pipeconf.module.ts
+++ b/web/gui2/src/main/webapp/app/view/pipeconf/pipeconf.module.ts
@@ -18,14 +18,13 @@
 import {CommonModule} from '@angular/common';
 import {PipeconfComponent} from './pipeconf/pipeconf.component';
 import {PipeconfDetailsComponent} from './pipeconfdetails/pipeconfdetails.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import {FormsModule} from '@angular/forms';
 import {RouterModule} from '@angular/router';
 
 @NgModule({
     imports: [
         CommonModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: PipeconfComponent}]),
         Gui2FwLibModule,
         FormsModule
diff --git a/web/gui2/src/main/webapp/app/view/pipeconf/pipeconf/pipeconf.component.ts b/web/gui2/src/main/webapp/app/view/pipeconf/pipeconf/pipeconf.component.ts
index d5aa2d3..50141c7 100644
--- a/web/gui2/src/main/webapp/app/view/pipeconf/pipeconf/pipeconf.component.ts
+++ b/web/gui2/src/main/webapp/app/view/pipeconf/pipeconf/pipeconf.component.ts
@@ -20,7 +20,7 @@
     LogService, SortDir,
     TableBaseImpl,
     WebSocketService
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {ActivatedRoute, Router} from '@angular/router';
 
 const pipeconfReq = 'pipeconfRequest';
diff --git a/web/gui2/src/main/webapp/app/view/pipeconf/pipeconfdetails/pipeconfdetails.component.ts b/web/gui2/src/main/webapp/app/view/pipeconf/pipeconfdetails/pipeconfdetails.component.ts
index 9057521..e5539f8 100644
--- a/web/gui2/src/main/webapp/app/view/pipeconf/pipeconfdetails/pipeconfdetails.component.ts
+++ b/web/gui2/src/main/webapp/app/view/pipeconf/pipeconfdetails/pipeconfdetails.component.ts
@@ -26,7 +26,7 @@
     FnService,
     IconService,
     LogService, WebSocketService
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import {PipeconfAction, PipeconfTable} from '../pipeconf/pipeconf.component';
 import {animate, state, style, transition, trigger} from '@angular/animations';
 
diff --git a/web/gui2/src/main/webapp/app/view/port/BUILD.bazel b/web/gui2/src/main/webapp/app/view/port/BUILD.bazel
index aa6c632..8b15b6f 100644
--- a/web/gui2/src/main/webapp/app/view/port/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/port/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-port",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/port/port.module.ts b/web/gui2/src/main/webapp/app/view/port/port.module.ts
index eab8095..1cb44b4 100644
--- a/web/gui2/src/main/webapp/app/view/port/port.module.ts
+++ b/web/gui2/src/main/webapp/app/view/port/port.module.ts
@@ -16,7 +16,7 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { PortComponent } from './port/port.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { FormsModule } from '@angular/forms';
 import { PortDetailsComponent } from './portdetails/portdetails.component';
 import {RouterModule} from '@angular/router';
@@ -25,7 +25,6 @@
     imports: [
         CommonModule,
         Gui2FwLibModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: PortComponent}]),
         FormsModule
     ],
diff --git a/web/gui2/src/main/webapp/app/view/port/port/port.component.ts b/web/gui2/src/main/webapp/app/view/port/port/port.component.ts
index c850d2a..a0482ae 100644
--- a/web/gui2/src/main/webapp/app/view/port/port/port.component.ts
+++ b/web/gui2/src/main/webapp/app/view/port/port/port.component.ts
@@ -20,7 +20,7 @@
     PrefsService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { ActivatedRoute } from '@angular/router';
 
 /**
diff --git a/web/gui2/src/main/webapp/app/view/port/portdetails/portdetails.component.ts b/web/gui2/src/main/webapp/app/view/port/portdetails/portdetails.component.ts
index 30d59f1..d2479ac5 100644
--- a/web/gui2/src/main/webapp/app/view/port/portdetails/portdetails.component.ts
+++ b/web/gui2/src/main/webapp/app/view/port/portdetails/portdetails.component.ts
@@ -21,7 +21,7 @@
     LogService,
     DetailsPanelBaseImpl,
     WebSocketService
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * The details view when a port row is clicked from the Port view
diff --git a/web/gui2/src/main/webapp/app/view/processor/BUILD.bazel b/web/gui2/src/main/webapp/app/view/processor/BUILD.bazel
index feb6ae6..5ea3000 100644
--- a/web/gui2/src/main/webapp/app/view/processor/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/processor/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-processor",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/processor/processor.module.ts b/web/gui2/src/main/webapp/app/view/processor/processor.module.ts
index e6d8a21..d73fbfc 100644
--- a/web/gui2/src/main/webapp/app/view/processor/processor.module.ts
+++ b/web/gui2/src/main/webapp/app/view/processor/processor.module.ts
@@ -15,14 +15,13 @@
  */
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { ProcessorComponent } from './processor/processor.component';
 import {RouterModule} from '@angular/router';
 
 @NgModule({
     imports: [
         CommonModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: ProcessorComponent}]),
         Gui2FwLibModule
     ],
diff --git a/web/gui2/src/main/webapp/app/view/processor/processor/processor.component.ts b/web/gui2/src/main/webapp/app/view/processor/processor/processor.component.ts
index 5083dcd..af63504 100644
--- a/web/gui2/src/main/webapp/app/view/processor/processor/processor.component.ts
+++ b/web/gui2/src/main/webapp/app/view/processor/processor/processor.component.ts
@@ -19,7 +19,7 @@
     LogService,
     WebSocketService,
     TableBaseImpl
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { ActivatedRoute } from '@angular/router';
 
 /**
diff --git a/web/gui2/src/main/webapp/app/view/settings/BUILD.bazel b/web/gui2/src/main/webapp/app/view/settings/BUILD.bazel
index 0802afe..f4a2f6d 100644
--- a/web/gui2/src/main/webapp/app/view/settings/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/settings/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-settings",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/settings/settings.module.ts b/web/gui2/src/main/webapp/app/view/settings/settings.module.ts
index 7e89942..1c66849 100644
--- a/web/gui2/src/main/webapp/app/view/settings/settings.module.ts
+++ b/web/gui2/src/main/webapp/app/view/settings/settings.module.ts
@@ -17,14 +17,13 @@
 import { CommonModule } from '@angular/common';
 
 import { SettingsComponent } from './settings/settings.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import { SettingsDetailsComponent } from './settingsdetails/settingsdetails.component';
 import {RouterModule} from '@angular/router';
 
 @NgModule({
     imports: [
         CommonModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: SettingsComponent}]),
         Gui2FwLibModule
     ],
diff --git a/web/gui2/src/main/webapp/app/view/settings/settings/settings.component.ts b/web/gui2/src/main/webapp/app/view/settings/settings/settings.component.ts
index 67fd073..fd6429b 100644
--- a/web/gui2/src/main/webapp/app/view/settings/settings/settings.component.ts
+++ b/web/gui2/src/main/webapp/app/view/settings/settings/settings.component.ts
@@ -19,7 +19,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * Model of the data returned through the Web Socket about settings.
diff --git a/web/gui2/src/main/webapp/app/view/settings/settingsdetails/settingsdetails.component.ts b/web/gui2/src/main/webapp/app/view/settings/settingsdetails/settingsdetails.component.ts
index ba2ce78..f0fd6e9 100644
--- a/web/gui2/src/main/webapp/app/view/settings/settingsdetails/settingsdetails.component.ts
+++ b/web/gui2/src/main/webapp/app/view/settings/settingsdetails/settingsdetails.component.ts
@@ -19,7 +19,7 @@
     LogService,
     DetailsPanelBaseImpl,
     WebSocketService
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 import { trigger, state, style, transition, animate } from '@angular/animations';
 import { Settings } from '../settings/settings.component';
 
diff --git a/web/gui2/src/main/webapp/app/view/tunnel/BUILD.bazel b/web/gui2/src/main/webapp/app/view/tunnel/BUILD.bazel
index b63d67d..4cc24e3 100644
--- a/web/gui2/src/main/webapp/app/view/tunnel/BUILD.bazel
+++ b/web/gui2/src/main/webapp/app/view/tunnel/BUILD.bazel
@@ -33,6 +33,7 @@
         "**/*.html",
     ]),
     module_name = "gui2-view-tunnel",
+    tsconfig = "//web/gui2:tsconfig.json",
     deps = [
         "//web/gui2-fw-lib",
         "@npm//@angular/animations",
diff --git a/web/gui2/src/main/webapp/app/view/tunnel/tunnel.module.ts b/web/gui2/src/main/webapp/app/view/tunnel/tunnel.module.ts
index 0c50567..48f5cdb 100644
--- a/web/gui2/src/main/webapp/app/view/tunnel/tunnel.module.ts
+++ b/web/gui2/src/main/webapp/app/view/tunnel/tunnel.module.ts
@@ -17,13 +17,12 @@
 import {CommonModule} from '@angular/common';
 
 import {TunnelComponent} from './tunnel/tunnel.component';
-import { Gui2FwLibModule } from '../../../../../../../gui2-fw-lib/public_api';
+import { Gui2FwLibModule } from 'gui2-fw-lib/public_api';
 import {RouterModule} from '@angular/router';
 
 @NgModule({
     imports: [
         CommonModule,
-        RouterModule,
         RouterModule.forChild([{path: '', component: TunnelComponent}]),
         Gui2FwLibModule
     ],
diff --git a/web/gui2/src/main/webapp/app/view/tunnel/tunnel/tunnel.component.ts b/web/gui2/src/main/webapp/app/view/tunnel/tunnel/tunnel.component.ts
index 6e5556d..93f2735 100644
--- a/web/gui2/src/main/webapp/app/view/tunnel/tunnel/tunnel.component.ts
+++ b/web/gui2/src/main/webapp/app/view/tunnel/tunnel/tunnel.component.ts
@@ -19,7 +19,7 @@
     LogService,
     WebSocketService,
     SortDir, TableBaseImpl, TableResponse
-} from '../../../../../../../../gui2-fw-lib/public_api';
+} from 'gui2-fw-lib/public_api';
 
 /**
  * Model of the response from WebSocket
diff --git a/web/gui2/src/main/webapp/initialize_testbed.ts b/web/gui2/src/main/webapp/initialize_testbed.ts
new file mode 100644
index 0000000..68a9b1c
--- /dev/null
+++ b/web/gui2/src/main/webapp/initialize_testbed.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Provides a script to initialize TestBed before tests are run.
+ * This file should be included in the "runtime_deps" of a "karma_web_test_suite"
+ * rule.
+ */
+import {TestBed} from '@angular/core/testing';
+import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing';
+
+TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
diff --git a/web/gui2/src/main/webapp/onos.dev.ts b/web/gui2/src/main/webapp/onos.dev.ts
new file mode 100644
index 0000000..aa063b6
--- /dev/null
+++ b/web/gui2/src/main/webapp/onos.dev.ts
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Used to launch the application under Bazel development mode.
+ */
+import {platformBrowser} from '@angular/platform-browser';
+import {OnosModule} from './app/onos.module';
+
+platformBrowser().bootstrapModule(OnosModule);
diff --git a/web/gui2/src/main/webapp/rxjs_shims.js b/web/gui2/src/main/webapp/rxjs_shims.js
new file mode 100644
index 0000000..2c80665
--- /dev/null
+++ b/web/gui2/src/main/webapp/rxjs_shims.js
@@ -0,0 +1,44 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+/**
+ * @fileoverview these provide named UMD modules so that we can bundle
+ * the application along with rxjs using the concatjs bundler.
+ */
+
+// rxjs/operators
+(function(factory) {
+    if (typeof module === 'object' && typeof module.exports === 'object') {
+        var v = factory(require, exports);
+        if (v !== undefined) module.exports = v;
+    } else if (typeof define === 'function' && define.amd) {
+        define('rxjs/operators', ['exports', 'rxjs'], factory);
+    }
+})(function(exports, rxjs) {
+    'use strict';
+    Object.keys(rxjs.operators).forEach(function(key) {
+        exports[key] = rxjs.operators[key];
+    });
+    Object.defineProperty(exports, '__esModule', {value: true});
+});
+
+// rxjs/testing
+(function(factory) {
+    if (typeof module === 'object' && typeof module.exports === 'object') {
+        var v = factory(require, exports);
+        if (v !== undefined) module.exports = v;
+    } else if (typeof define === 'function' && define.amd) {
+        define('rxjs/testing', ['exports', 'rxjs'], factory);
+    }
+})(function(exports, rxjs) {
+    'use strict';
+    Object.keys(rxjs.testing).forEach(function(key) {
+        exports[key] = rxjs.testing[key];
+    });
+    Object.defineProperty(exports, '__esModule', {value: true});
+});
diff --git a/web/gui2/tsconfig-test.json b/web/gui2/tsconfig-test.json
new file mode 100644
index 0000000..d4165e8
--- /dev/null
+++ b/web/gui2/tsconfig-test.json
@@ -0,0 +1,6 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "types": ["jasmine"]
+  }
+}
diff --git a/tsconfig.json b/web/gui2/tsconfig.json
similarity index 82%
rename from tsconfig.json
rename to web/gui2/tsconfig.json
index e9341ca..4580e39 100644
--- a/tsconfig.json
+++ b/web/gui2/tsconfig.json
@@ -10,13 +10,14 @@
       "es2017",
       "es2017.object"
     ],
-    // Permit decorator syntax
-    "experimentalDecorators": true,
     // Don't scan the node_modules/@types folder for ambient types.
     // This would force us to have all the types in the dependencies of
     // each library.
     // Instead we'll be explicit about declaring ambient type dependencies
     // using the ///<reference types=""/> syntax.
-    "types": []
+    "types": [],
+    "paths": {
+      "org_onosproject_onos/web/gui2-fw-lib": ["web/gui2-fw-lib"]
+    }
   }
 }
diff --git a/web/gui2/yarn.lock b/web/gui2/yarn.lock
index a636589..fa26048 100644
--- a/web/gui2/yarn.lock
+++ b/web/gui2/yarn.lock
@@ -106,6 +106,13 @@
   resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.0.0-rc.7.tgz#0b0bfd3d60c3456b4eb0f7bf1dfeec97d04458ba"
   integrity sha512-hY/Dn2zg/yQb8Qk7a8RiwGJrankQAJssV4JJZSBuVGgtbdhdKv1+u9xNVcqYPlY+WuBhyvU+WoRWlooMv3c1AA==
 
+"@angular/http@^7.2.15":
+  version "7.2.15"
+  resolved "https://registry.yarnpkg.com/@angular/http/-/http-7.2.15.tgz#a32bea9e67e99eef88150085aeebbe7aeecd39eb"
+  integrity sha512-TR7PEdmLWNIre3Zn8lvyb4lSrvPUJhKLystLnp4hBMcWsJqq5iK8S3bnlR4viZ9HMlf7bW7+Hm4SI6aB3tdUtw==
+  dependencies:
+    tslib "^1.9.0"
+
 "@angular/platform-browser-dynamic@9.0.0-rc.7":
   version "9.0.0-rc.7"
   resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.0.0-rc.7.tgz#9bfe1a8776c8bcae95f42a7dd003aa908c9f3a09"
@@ -121,60 +128,6 @@
   resolved "https://registry.yarnpkg.com/@angular/router/-/router-9.0.0-rc.7.tgz#9c042e8832df1c20bcbf16d0994df6ace68699db"
   integrity sha512-6kviTBp43UyYj/Ah4qMhoga5YVHTVf3fmvbA4ETfTZAV0IEiPahxhn3FJ5Yal9Lk6Fc2kGmDvuDJgbn7gNbppA==
 
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5":
-  version "7.5.5"
-  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
-  integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
-  dependencies:
-    "@babel/highlight" "^7.0.0"
-
-"@babel/generator@^7.4.0", "@babel/generator@^7.7.4":
-  version "7.7.7"
-  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45"
-  integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==
-  dependencies:
-    "@babel/types" "^7.7.4"
-    jsesc "^2.5.1"
-    lodash "^4.17.13"
-    source-map "^0.5.0"
-
-"@babel/helper-function-name@^7.7.4":
-  version "7.7.4"
-  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e"
-  integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==
-  dependencies:
-    "@babel/helper-get-function-arity" "^7.7.4"
-    "@babel/template" "^7.7.4"
-    "@babel/types" "^7.7.4"
-
-"@babel/helper-get-function-arity@^7.7.4":
-  version "7.7.4"
-  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0"
-  integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==
-  dependencies:
-    "@babel/types" "^7.7.4"
-
-"@babel/helper-split-export-declaration@^7.7.4":
-  version "7.7.4"
-  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8"
-  integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==
-  dependencies:
-    "@babel/types" "^7.7.4"
-
-"@babel/highlight@^7.0.0":
-  version "7.5.0"
-  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540"
-  integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==
-  dependencies:
-    chalk "^2.0.0"
-    esutils "^2.0.2"
-    js-tokens "^4.0.0"
-
-"@babel/parser@^7.4.3", "@babel/parser@^7.7.4":
-  version "7.7.7"
-  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937"
-  integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw==
-
 "@babel/runtime@^7.3.1":
   version "7.7.7"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.7.tgz#194769ca8d6d7790ec23605af9ee3e42a0aa79cf"
@@ -182,70 +135,37 @@
   dependencies:
     regenerator-runtime "^0.13.2"
 
-"@babel/template@^7.4.0", "@babel/template@^7.7.4":
-  version "7.7.4"
-  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
-  integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==
-  dependencies:
-    "@babel/code-frame" "^7.0.0"
-    "@babel/parser" "^7.7.4"
-    "@babel/types" "^7.7.4"
-
-"@babel/traverse@^7.4.3":
-  version "7.7.4"
-  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558"
-  integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==
-  dependencies:
-    "@babel/code-frame" "^7.5.5"
-    "@babel/generator" "^7.7.4"
-    "@babel/helper-function-name" "^7.7.4"
-    "@babel/helper-split-export-declaration" "^7.7.4"
-    "@babel/parser" "^7.7.4"
-    "@babel/types" "^7.7.4"
-    debug "^4.1.0"
-    globals "^11.1.0"
-    lodash "^4.17.13"
-
-"@babel/types@^7.4.0", "@babel/types@^7.7.4":
-  version "7.7.4"
-  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193"
-  integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==
-  dependencies:
-    esutils "^2.0.2"
-    lodash "^4.17.13"
-    to-fast-properties "^2.0.0"
-
 "@bazel/hide-bazel-files@1.0.0":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@bazel/hide-bazel-files/-/hide-bazel-files-1.0.0.tgz#779070dcb5ae121ff6c72d73bf3fb7bf68285d75"
   integrity sha512-dfw2W7xDUPlRMcDMVO8gDkX9Xb7Thy3sP4PDODv+eiHOvwIi116X/wwy7mQUZISkJdEJ1zWy9ydpzvfetpYh4w==
 
-"@bazel/karma@^1.0.0":
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/@bazel/karma/-/karma-1.0.0.tgz#6f1e31bc2cb698e50d76f43ec9f1ee095d8e72b8"
-  integrity sha512-esfsHRVWVcp6OyTk/QI1sBV7bcygFiXY6LUMPLPYqVZkQvJ0x+/L1weiwuRrqFf+FCwCajhYjwiR6S9kX2Z9LA==
+"@bazel/karma@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@bazel/karma/-/karma-1.0.1.tgz#f60de501367125ece03af1250ccb69d836fee2cc"
+  integrity sha512-AJ7KOx+oWHTAwstTMH95jpPP4MSKnG2eZiTms5OilhLz6KWg+l4hGumJ+jB8ntt/ZlMv9nrLVohS5zjEUyeTYA==
   dependencies:
     tmp "0.1.0"
 
-"@bazel/protractor@^1.0.0":
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/@bazel/protractor/-/protractor-1.0.0.tgz#b77fde3bb53a008c330c13a953a0bf93aa06b5f1"
-  integrity sha512-8kGuM3NkFfokjzKBlYxK9rUwJO/ICnYTHC567KJk6T4pjm4kfyh6iVI3Df3K+ONRCEYmiuZrQ37U06lzMMGN9g==
+"@bazel/protractor@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@bazel/protractor/-/protractor-1.0.1.tgz#48d1f12c9edec114b04b45a159fa8c231c65c688"
+  integrity sha512-gAJ4nMQRXu4/k+EvH/aD4BUBrSy9dn/xtAI0qRs8t2997Zafb2HI0Ejd0Ep3geBcnloC/EWGSQAIBt5vQrOWAw==
 
-"@bazel/rollup@^1.0.0":
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/@bazel/rollup/-/rollup-1.0.0.tgz#85f38cf07ba8ea192e54c42cb53a44d1fd1f56ac"
-  integrity sha512-pOWwyeM/H+LWRpKm3xuSAXoZ1gl6o8kFh5ltf0tM+ZfqGnSNbakME6ZswfmVj7FHUgF40BXzSoFTUdqgn1xy/w==
+"@bazel/rollup@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@bazel/rollup/-/rollup-1.0.1.tgz#aaef886ff6cb00fc19995479aef4275359b57eee"
+  integrity sha512-LL9eszGoHbw50+59KqqgmHB1AFQKlYeJFDCMzJU5DnAMLWz/bSlf77CaC3iipL7AVQXVqu1aJEviiNYDVGTlig==
 
-"@bazel/terser@^1.0.0":
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/@bazel/terser/-/terser-1.0.0.tgz#f9ef724cd4a81776dae71ae904934994d5006960"
-  integrity sha512-L+Q7YH+OA0W7Qp30DrnTKdNA6gasip9CdzI0zSvFOk18B7XBR+WswkIY2RkwwhH+y4SROqkHbX16z02jDHsnng==
+"@bazel/terser@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@bazel/terser/-/terser-1.0.1.tgz#edc22ef7d507ddf249ab039fc9f8c4d05c4789f9"
+  integrity sha512-ldww7M6V6itnhCbtIdiGenKJZVwfpeA+h1z41KYCPQouNBrf0zBH717NYUx1IXkxmWfuT1cmgDWLYEhBC+R2Sw==
 
-"@bazel/typescript@1.0.0":
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-1.0.0.tgz#2c7318b9a3aaa730f282b094ddf41dd16fda7b5a"
-  integrity sha512-caNOKz7EjVMgbedjVTreao9++9Sb9oYlU2nqDOMIK8MyoOUQvgGQWhFwF65XXGSb79Tzv8kaFQskoaH/iAs4ng==
+"@bazel/typescript@1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-1.0.1.tgz#23c8232f9a08199971a306a688843f10832f2458"
+  integrity sha512-dEZVAqmsJRcxnUPedXJ5QJIcmzxxXLDSybNO2uBXET8PvDfRpFGwu/ui+FE3uC3gYYXUFUas6WIEw5oiSeicVQ==
   dependencies:
     protobufjs "6.8.8"
     semver "5.6.0"
@@ -470,10 +390,10 @@
   resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
   integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
 
-"@types/jasmine@~3.3.8":
-  version "3.3.16"
-  resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.3.16.tgz#7c84074f5d7f84da9a14f816ccfb9aeb4da13f27"
-  integrity sha512-Nveep4zKGby8uIvG2AEUyYOwZS8uVeHK9TgbuWYSawUDDdIgfhCKz28QzamTo//Jk7Ztt9PO3f+vzlB6a4GV1Q==
+"@types/jasmine@~3.4.0":
+  version "3.4.6"
+  resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.4.6.tgz#afcb210af0fa751b85a96b2034eedada65390be1"
+  integrity sha512-hpQHs+lmZ0uuCrGyqypdI1Ho7jRFolOBT6OkNdZPFziLSSEKvWu+VxWU6bGdNEA/hoV4jV8pdDeNx8EWlmfNAw==
 
 "@types/long@^4.0.0":
   version "4.0.0"
@@ -485,6 +405,11 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.2.tgz#fe94285bf5e0782e1a9e5a8c482b1c34465fa385"
   integrity sha512-B8emQA1qeKerqd1dmIsQYnXi+mmAzTB7flExjmy5X1aVAKFNNNDubkavwR13kR6JnpeLp3aLoJhwn9trWPAyFQ==
 
+"@types/node@6.14.9":
+  version "6.14.9"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-6.14.9.tgz#733583e21ef0eab85a9737dfafbaa66345a92ef0"
+  integrity sha512-leP/gxHunuazPdZaCvsCefPQxinqUDsCxCR5xaDUrY2MkYxQRFZZwU5e7GojyYsGB7QVtCi7iVEl/hoFXQYc+w==
+
 "@types/node@8.10.54":
   version "8.10.54"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.54.tgz#1c88eb253ac1210f1a5876953fb70f7cc4928402"
@@ -495,11 +420,6 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.13.tgz#ccebcdb990bd6139cd16e84c39dc2fb1023ca90c"
   integrity sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==
 
-"@types/node@~8.9.4":
-  version "8.9.5"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.9.5.tgz#162b864bc70be077e6db212b322754917929e976"
-  integrity sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ==
-
 "@types/q@^0.0.32":
   version "0.0.32"
   resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5"
@@ -706,13 +626,6 @@
   resolved "https://registry.yarnpkg.com/apache-md5/-/apache-md5-1.1.2.tgz#ee49736b639b4f108b6e9e626c6da99306b41692"
   integrity sha1-7klza2ObTxCLbp5ibG2pkwa0FpI=
 
-append-transform@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab"
-  integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==
-  dependencies:
-    default-require-extensions "^2.0.0"
-
 aproba@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -1230,7 +1143,7 @@
     strip-ansi "^3.0.0"
     supports-color "^2.0.0"
 
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.2:
+chalk@^2.0.1, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
   integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -1386,11 +1299,6 @@
   resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
   integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
 
-colors@1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
-  integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM=
-
 colors@^1.1.0, colors@^1.4.0, colors@latest:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
@@ -1418,11 +1326,6 @@
   resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e"
   integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==
 
-compare-versions@^3.4.0:
-  version "3.5.1"
-  resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.5.1.tgz#26e1f5cf0d48a77eced5046b9f67b6b61075a393"
-  integrity sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg==
-
 component-bind@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
@@ -1915,7 +1818,7 @@
   dependencies:
     ms "^2.1.1"
 
-debug@^4.1.0, debug@^4.1.1:
+debug@^4.1.1:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
   integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
@@ -1966,13 +1869,6 @@
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
   integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
 
-default-require-extensions@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7"
-  integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=
-  dependencies:
-    strip-bom "^3.0.0"
-
 defaults@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
@@ -2707,14 +2603,6 @@
   resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
   integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
 
-fileset@^2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
-  integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
-  dependencies:
-    glob "^7.0.3"
-    minimatch "^3.0.3"
-
 fill-range@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@@ -3017,11 +2905,6 @@
   dependencies:
     ini "^1.3.4"
 
-globals@^11.1.0:
-  version "11.12.0"
-  resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
-  integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-
 globby@^5.0.0:
   version "5.0.0"
   resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
@@ -3069,7 +2952,7 @@
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
   integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
 
-handlebars@^4.1.2, handlebars@^4.3.3:
+handlebars@^4.3.3:
   version "4.5.3"
   resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482"
   integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==
@@ -3186,6 +3069,14 @@
   resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
   integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=
 
+html-insert-assets@^0.4.0:
+  version "0.4.3"
+  resolved "https://registry.yarnpkg.com/html-insert-assets/-/html-insert-assets-0.4.3.tgz#8673c4c89f78e3547cac395cf0e1591fa7ec6f00"
+  integrity sha512-X+uHs3XzqM8KP6acCKYkbdKvonAJuLutanmCXxp6zmUXCBfa7Nksy7CyDkf9rwcCn+LrMquEfD1WXwwRF6cD1g==
+  dependencies:
+    mkdirp "^0.5.1"
+    parse5 "^5.1.1"
+
 htmlparser2@^3.9.1:
   version "3.10.1"
   resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
@@ -3779,77 +3670,6 @@
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
   integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
 
-istanbul-api@^2.1.6:
-  version "2.1.6"
-  resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.6.tgz#d61702a9d1c66ad89d92e66d401e16b0bda4a35f"
-  integrity sha512-x0Eicp6KsShG1k1rMgBAi/1GgY7kFGEBwQpw3PXGEmu+rBcBNhqU8g2DgY9mlepAsLPzrzrbqSgCGANnki4POA==
-  dependencies:
-    async "^2.6.2"
-    compare-versions "^3.4.0"
-    fileset "^2.0.3"
-    istanbul-lib-coverage "^2.0.5"
-    istanbul-lib-hook "^2.0.7"
-    istanbul-lib-instrument "^3.3.0"
-    istanbul-lib-report "^2.0.8"
-    istanbul-lib-source-maps "^3.0.6"
-    istanbul-reports "^2.2.4"
-    js-yaml "^3.13.1"
-    make-dir "^2.1.0"
-    minimatch "^3.0.4"
-    once "^1.4.0"
-
-istanbul-lib-coverage@^2.0.5:
-  version "2.0.5"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49"
-  integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==
-
-istanbul-lib-hook@^2.0.7:
-  version "2.0.7"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133"
-  integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==
-  dependencies:
-    append-transform "^1.0.0"
-
-istanbul-lib-instrument@^3.3.0:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630"
-  integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==
-  dependencies:
-    "@babel/generator" "^7.4.0"
-    "@babel/parser" "^7.4.3"
-    "@babel/template" "^7.4.0"
-    "@babel/traverse" "^7.4.3"
-    "@babel/types" "^7.4.0"
-    istanbul-lib-coverage "^2.0.5"
-    semver "^6.0.0"
-
-istanbul-lib-report@^2.0.8:
-  version "2.0.8"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33"
-  integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==
-  dependencies:
-    istanbul-lib-coverage "^2.0.5"
-    make-dir "^2.1.0"
-    supports-color "^6.1.0"
-
-istanbul-lib-source-maps@^3.0.6:
-  version "3.0.6"
-  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8"
-  integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==
-  dependencies:
-    debug "^4.1.1"
-    istanbul-lib-coverage "^2.0.5"
-    make-dir "^2.1.0"
-    rimraf "^2.6.3"
-    source-map "^0.6.1"
-
-istanbul-reports@^2.2.4:
-  version "2.2.6"
-  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af"
-  integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==
-  dependencies:
-    handlebars "^4.1.2"
-
 jasmine-core@^3.3:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.5.0.tgz#132c23e645af96d85c8bca13c8758b18429fc1e4"
@@ -3860,18 +3680,6 @@
   resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e"
   integrity sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=
 
-jasmine-core@~3.4.0:
-  version "3.4.0"
-  resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.4.0.tgz#2a74618e966026530c3518f03e9f845d26473ce3"
-  integrity sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==
-
-jasmine-spec-reporter@~4.2.1:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz#1d632aec0341670ad324f92ba84b4b32b35e9e22"
-  integrity sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==
-  dependencies:
-    colors "1.1.2"
-
 jasmine@2.8.0:
   version "2.8.0"
   resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.8.0.tgz#6b089c0a11576b1f16df11b80146d91d4e8b8a3e"
@@ -3891,11 +3699,6 @@
   resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a"
   integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo=
 
-js-tokens@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
-  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-
 js-yaml@^3.13.1:
   version "3.13.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
@@ -3909,11 +3712,6 @@
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
   integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
 
-jsesc@^2.5.1:
-  version "2.5.2"
-  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
-  integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
-
 json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@@ -3981,14 +3779,6 @@
     fs-access "^1.0.0"
     which "^1.2.1"
 
-karma-coverage-istanbul-reporter@~2.0.1:
-  version "2.0.6"
-  resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.6.tgz#7b6e9c88781447bb87aa6ac24bf74b93e558adc3"
-  integrity sha512-WFh77RI8bMIKdOvI/1/IBmgnM+Q7NOLhnwG91QJrM8lW+CIXCjTzhhUsT/svLvAkLmR10uWY4RyYbHMLkTglvg==
-  dependencies:
-    istanbul-api "^2.1.6"
-    minimatch "^3.0.4"
-
 karma-firefox-launcher@^1.1.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/karma-firefox-launcher/-/karma-firefox-launcher-1.2.0.tgz#64fe03dd10300f9754d48f9ebfbf31f6c94a200c"
@@ -4003,6 +3793,18 @@
   dependencies:
     jasmine-core "^3.3"
 
+karma-requirejs@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/karma-requirejs/-/karma-requirejs-1.1.0.tgz#fddae2cb87d7ebc16fb0222893564d7fee578798"
+  integrity sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=
+
+karma-sourcemap-loader@0.3.7:
+  version "0.3.7"
+  resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8"
+  integrity sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=
+  dependencies:
+    graceful-fs "^4.1.2"
+
 karma@~4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/karma/-/karma-4.1.0.tgz#d07387c9743a575b40faf73e8a3eb5421c2193e1"
@@ -4142,7 +3944,7 @@
   resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
   integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
 
-lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.15:
+lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.15:
   version "4.17.15"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@@ -4231,14 +4033,6 @@
   dependencies:
     pify "^3.0.0"
 
-make-dir@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
-  integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
-  dependencies:
-    pify "^4.0.1"
-    semver "^5.6.0"
-
 make-fetch-happen@^5.0.0:
   version "5.0.2"
   resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd"
@@ -4367,7 +4161,7 @@
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
   integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
 
-minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
+minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -4954,6 +4748,11 @@
   dependencies:
     "@types/node" "*"
 
+parse5@^5.1.1:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
+  integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
+
 parseqs@0.0.5:
   version "0.0.5"
   resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
@@ -5086,11 +4885,6 @@
   resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
   integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
 
-pify@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
-  integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
-
 pinkie-promise@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
@@ -5478,6 +5272,11 @@
   resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
   integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
 
+requirejs@2.3.6:
+  version "2.3.6"
+  resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9"
+  integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==
+
 requires-port@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
@@ -5707,7 +5506,7 @@
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
   integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
 
-semver@6.3.0, semver@^6.0.0, semver@^6.3.0:
+semver@6.3.0, semver@^6.3.0:
   version "6.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@@ -5971,7 +5770,7 @@
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
   integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
 
-source-map@^0.5.0, source-map@^0.5.6:
+source-map@^0.5.6:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -6244,11 +6043,6 @@
   dependencies:
     ansi-regex "^5.0.0"
 
-strip-bom@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
-  integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
-
 strip-eof@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@@ -6271,13 +6065,6 @@
   dependencies:
     has-flag "^3.0.0"
 
-supports-color@^6.1.0:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
-  integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
-  dependencies:
-    has-flag "^3.0.0"
-
 svg-to-pdfkit@^0.1.8:
   version "0.1.8"
   resolved "https://registry.yarnpkg.com/svg-to-pdfkit/-/svg-to-pdfkit-0.1.8.tgz#5921765922044843f0c1a5b25ec1ef8a4a33b8af"
@@ -6378,11 +6165,6 @@
   resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
   integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA=
 
-to-fast-properties@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
-  integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
-
 to-object-path@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"