This is an automated email from the ASF dual-hosted git repository.

ocket8888 pushed a commit to branch 5.0.x
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git

commit a9e53424618b71ab686d1953d1fafe5f5b2707de
Author: Zach Hoffman <[email protected]>
AuthorDate: Thu Oct 29 11:26:15 2020 -0600

    Enable includeSystemTests in the API tests GitHub Action (#5168)
    
    * Add Riak server to TO integration tests action
    
    * Add SMTP server to TO integration tests action
    
    * Specify inputs in action.yml
    
    * Declare $trafficvault outside of start_trafic_vault() because variables
    declared inside of functions are local in Almquist Shell
    
    * Show (and colorize) Traffic Ops logs in real time instead of after tests
    run
    
    * Make "Run API Tests" a JavaScript action
    
    * Add a newline
    
    * Add license to .eslintrc
    
    * Remove unused JS file
    
    * Remove unnecessary cats
    
    * Define yellow_bg
    
    * Remove redundant `docker rm`
    
    * Gitignore GitHub Actions node_modules
    
    * Use tabs
    
    * Add pickier eslintrc, courtesy of @ocket8888
    
    * Satisfy new eslintrc
    
    * Use ?? 1 instead of || 1
    
    * Set "browser" to false in elintrc
    
    * Rebuild script
    
    (cherry picked from commit 4cd6fbace3c450b5345141e4fb38cdd54b040e29)
---
 .github/actions/to-integration-tests/.eslintrc     |  333 ++++
 .github/actions/to-integration-tests/Dockerfile    |   32 -
 .github/actions/to-integration-tests/README.md     |   34 +-
 .github/actions/to-integration-tests/action.yml    |   20 +-
 .github/actions/to-integration-tests/cdn.json      |   59 +-
 .github/actions/to-integration-tests/database.json |    2 +-
 .github/actions/to-integration-tests/dbconf.yml    |    2 +-
 .../dist/to-integration-tests.js                   |   31 +
 .github/actions/to-integration-tests/entrypoint.sh |  129 +-
 .../actions/to-integration-tests/package-lock.json | 1994 ++++++++++++++++++++
 .github/actions/to-integration-tests/package.json  |   24 +
 .github/actions/to-integration-tests/riak.json     |    8 +
 .../to-integration-tests/to-integration-tests.ts   |   31 +
 .../to-integration-tests/traffic-ops-test.json     |    7 +-
 .github/actions/to-integration-tests/tsconfig.json |   14 +
 .github/workflows/traffic ops.yml                  |   16 +
 .gitignore                                         |    1 +
 .../testing/api/v3/serverservercapability_test.go  |    4 +-
 traffic_ops/testing/api/v3/tc-fixtures.json        |    6 +-
 19 files changed, 2644 insertions(+), 103 deletions(-)

diff --git a/.github/actions/to-integration-tests/.eslintrc 
b/.github/actions/to-integration-tests/.eslintrc
new file mode 100644
index 0000000..f7ae69c
--- /dev/null
+++ b/.github/actions/to-integration-tests/.eslintrc
@@ -0,0 +1,333 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership.  The ASF
+ * licenses this file to you 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.
+ */
+{
+       "env": {
+               "browser": false,
+               "es6": true,
+               "node": true
+       },
+       "parser": "@typescript-eslint/parser",
+       "parserOptions": {
+               "project": "tsconfig.json",
+               "sourceType": "module"
+       },
+       "plugins": [
+               "eslint-plugin-jsdoc",
+               "eslint-plugin-import",
+               "@typescript-eslint",
+               "@typescript-eslint/tslint"
+       ],
+       "rules": {
+               "@typescript-eslint/array-type": "off",
+               "@typescript-eslint/await-thenable": "error",
+               "@typescript-eslint/consistent-type-assertions": "error",
+               "@typescript-eslint/consistent-type-definitions": "error",
+               "@typescript-eslint/dot-notation": "error",
+               "@typescript-eslint/explicit-function-return-type": "error",
+               "@typescript-eslint/explicit-member-accessibility": [
+                       "error",
+                       {
+                               "accessibility": "explicit"
+                       }
+               ],
+               "@typescript-eslint/explicit-module-boundary-types": "error",
+               "@typescript-eslint/indent": [
+                       "off",
+                       "tab"
+               ],
+               "@typescript-eslint/member-delimiter-style": [
+                       "error",
+                       {
+                               "multiline": {
+                                       "delimiter": "none",
+                                       "requireLast": true
+                               },
+                               "singleline": {
+                                       "delimiter": "semi",
+                                       "requireLast": false
+                               }
+                       }
+               ],
+               "@typescript-eslint/member-ordering": "error",
+               "@typescript-eslint/naming-convention": "error",
+               "@typescript-eslint/no-empty-function": "error",
+               "@typescript-eslint/no-empty-interface": "error",
+               "@typescript-eslint/no-explicit-any": "error",
+               "@typescript-eslint/no-extraneous-class": "error",
+               "@typescript-eslint/no-floating-promises": "off",
+               "@typescript-eslint/no-inferrable-types": [
+                       "error",
+                       {
+                               "ignoreParameters": true
+                       }
+               ],
+               "@typescript-eslint/no-misused-new": "error",
+               "@typescript-eslint/no-non-null-assertion": "error",
+               "@typescript-eslint/no-require-imports": "error",
+               "@typescript-eslint/no-this-alias": "error",
+               "@typescript-eslint/no-unnecessary-boolean-literal-compare": 
"error",
+               "@typescript-eslint/no-unnecessary-qualifier": "error",
+               "@typescript-eslint/no-unnecessary-type-arguments": "error",
+               "@typescript-eslint/no-unnecessary-type-assertion": "error",
+               "@typescript-eslint/no-unused-expressions": "error",
+               "@typescript-eslint/no-unused-vars": "error",
+               "@typescript-eslint/no-use-before-define": "error",
+               "@typescript-eslint/no-var-requires": "off",
+               "@typescript-eslint/prefer-for-of": "error",
+               "@typescript-eslint/prefer-function-type": "error",
+               "@typescript-eslint/prefer-readonly": "error",
+               "@typescript-eslint/promise-function-async": "error",
+               "@typescript-eslint/quotes": [
+                       "error",
+                       "double"
+               ],
+               "@typescript-eslint/semi": [
+                       "error"
+               ],
+               "@typescript-eslint/tslint/config": [
+                       "error",
+                       {
+                               "rules": {
+                                       "completed-docs": [
+                                               true,
+                                               {
+                                                       "classes": {
+                                                               "visibilities": 
[
+                                                                       
"exported"
+                                                               ]
+                                                       }
+                                               },
+                                               {
+                                                       "enums": {
+                                                               "visibilities": 
[
+                                                                       
"exported"
+                                                               ]
+                                                       }
+                                               },
+                                               "enum-members",
+                                               {
+                                                       "functions": {
+                                                               "overloads": 
true,
+                                                               "visibilities": 
[
+                                                                       
"exported"
+                                                               ]
+                                                       }
+                                               },
+                                               {
+                                                       "interfaces": {
+                                                               "visibilities": 
[
+                                                                       
"exported"
+                                                               ]
+                                                       }
+                                               },
+                                               {
+                                                       "namespaces": {
+                                                               "visibilities": 
[
+                                                                       
"exported"
+                                                               ]
+                                                       }
+                                               },
+                                               {
+                                                       "types": {
+                                                               "visibilities": 
[
+                                                                       
"exported"
+                                                               ]
+                                                       }
+                                               },
+                                               {
+                                                       "variables": {
+                                                               "visibilities": 
[
+                                                                       
"exported"
+                                                               ]
+                                                       }
+                                               },
+                                               {
+                                                       "methods": {
+                                                               "overloads": 
true,
+                                                               "privacies": [
+                                                                       "public"
+                                                               ]
+                                                       }
+                                               },
+                                               {
+                                                       "properties": {
+                                                               "privacies": [
+                                                                       "public"
+                                                               ]
+                                                       }
+                                               }
+                                       ],
+                                       "import-spacing": true,
+                                       "invalid-void": true,
+                                       "no-dynamic-delete": true,
+                                       "no-inferred-empty-object-type": true,
+                                       "no-null-undefined-union": true,
+                                       "no-promise-as-boolean": true,
+                                       "no-tautology-expression": true,
+                                       "no-unnecessary-callback-wrapper": true,
+                                       "number-literal-format": true,
+                                       "object-literal-sort-keys": true,
+                                       "prefer-while": true,
+                                       "static-this": true,
+                                       "typedef": [
+                                               true,
+                                               "call-signature",
+                                               "parameter",
+                                               "property-declaration",
+                                               "member-variable",
+                                               "object-destructuring",
+                                               "array-destructuring"
+                                       ],
+                                       "unnecessary-else": true,
+                                       "whitespace": [
+                                               true,
+                                               "check-decl",
+                                               "check-module",
+                                               "check-separator",
+                                               "check-rest-spread",
+                                               "check-type",
+                                               "check-typecast",
+                                               "check-type-operator"
+                                       ]
+                               }
+                       }
+               ],
+               "@typescript-eslint/unbound-method": "error",
+               "arrow-body-style": "error",
+               "arrow-parens": [
+                       "off",
+                       "always"
+               ],
+               "class-methods-use-this": "error",
+               "comma-dangle": "off",
+               "constructor-super": "error",
+               "curly": "error",
+               "eol-last": "error",
+               "eqeqeq": [
+                       "error",
+                       "always"
+               ],
+               "id-blacklist": [
+                       "error",
+                       "any",
+                       "Number",
+                       "number",
+                       "String",
+                       "string",
+                       "Boolean",
+                       "boolean",
+                       "Undefined",
+                       "undefined"
+               ],
+               "id-match": "error",
+               "import/no-deprecated": "warn",
+               "import/order": "off",
+               "jsdoc/check-alignment": "error",
+               "jsdoc/check-indentation": "error",
+               "jsdoc/newline-after-description": "error",
+               "jsdoc/no-types": "error",
+               "linebreak-style": [
+                       "error",
+                       "unix"
+               ],
+               "max-classes-per-file": "off",
+               "max-len": [
+                       "error",
+                       {
+                               "code": 140
+                       }
+               ],
+               "new-parens": "error",
+               "no-caller": "error",
+               "no-console": [
+                       "error",
+                       {
+                               "allow": [
+                                       "assert",
+                                       "clear",
+                                       "Console",
+                                       "context",
+                                       "count",
+                                       "countReset",
+                                       "dir",
+                                       "dirxml",
+                                       "error",
+                                       "group",
+                                       "groupCollapsed",
+                                       "groupEnd",
+                                       "info",
+                                       "log",
+                                       "profile",
+                                       "profileEnd",
+                                       "table",
+                                       "timeLog",
+                                       "timeStamp",
+                                       "warn"
+                               ]
+                       }
+               ],
+               "no-debugger": "error",
+               "no-duplicate-case": "error",
+               "no-else-return": [
+                       "error",
+                       {
+                               "allowElseIf": false
+                       }
+               ],
+               "no-empty": "error",
+               "no-eval": "error",
+               "no-extra-bind": "error",
+               "no-fallthrough": "error",
+               "no-invalid-this": "error",
+               "no-multiple-empty-lines": "off",
+               "no-new-func": "error",
+               "no-redeclare": "error",
+               "no-restricted-imports": [
+                       "error",
+                       "rxjs/Rx"
+               ],
+               "no-return-await": "error",
+               "no-shadow": [
+                       "error",
+                       {
+                               "hoist": "all"
+                       }
+               ],
+               "no-sparse-arrays": "error",
+               "no-template-curly-in-string": "error",
+               "no-throw-literal": "error",
+               "no-trailing-spaces": "error",
+               "no-undef-init": "error",
+               "no-underscore-dangle": "error",
+               "no-unsafe-finally": "error",
+               "no-useless-constructor": "error",
+               "no-var": "error",
+               "one-var": [
+                       "error",
+                       "never"
+               ],
+               "prefer-const": "error",
+               "prefer-object-spread": "error",
+               "prefer-template": "error",
+               "quote-props": [
+                       "error",
+                       "as-needed"
+               ],
+               "radix": "error",
+               "use-isnan": "error"
+       }
+}
diff --git a/.github/actions/to-integration-tests/Dockerfile 
b/.github/actions/to-integration-tests/Dockerfile
deleted file mode 100644
index 661e0cf..0000000
--- a/.github/actions/to-integration-tests/Dockerfile
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-
-FROM alpine:3.12
-
-RUN architecture=$(uname -m) && \
-    mkdir lib64 && \
-    # Use musl libc where the go binary expects glibc
-    # Less-generalized: ln -s /lib/ld-musl-x86_64.so.1 
/lib64/ld-linux-x86-64.so.2
-    ln -s /lib/ld-musl-${architecture}.so.[0-9] 
/lib64/ld-linux-${architecture//_/-}.so.2
-ENV GOROOT=/usr/local/go \
-    CGO_ENABLED=0
-
-RUN apk add --no-cache gettext git
-
-COPY entrypoint.sh database.json traffic-ops-test.json cdn.json /
-
-ENTRYPOINT /entrypoint.sh
diff --git a/.github/actions/to-integration-tests/README.md 
b/.github/actions/to-integration-tests/README.md
index 6f81959..324e9b6 100644
--- a/.github/actions/to-integration-tests/README.md
+++ b/.github/actions/to-integration-tests/README.md
@@ -17,15 +17,28 @@
   under the License.
 -->
 
-# to-integration-tests Docker action
-This action runs the Traffic Ops Go client integration tests with the Traffic
-Ops API.
+# to-integration-tests JavaScript action
+This action runs the Traffic Ops Go client integration tests with the Traffic 
Ops API.
+- Requires an SMTP service (see `smtp_address` input)
+- Provides a Riak server at address `trafficvault.infra.ciab.test`
 
 ## Inputs
 
 ### `version`
 **Required** Major API version to test e.g. 1, 2, 3 etc.
 
+### `smtp_address`
+**Required** The address of an SMTP server for use by Traffic Ops.
+
+### `smtp_port`
+**Required** The address of an SMTP server for use by Traffic Ops. Required 
but defaults to `25`.
+
+### `smtp_user`
+**Optional** The user to authenticate with for the SMTP server.
+
+### `smtp_password`
+**Optional** The password to authenticate with for the SMTP server.
+
 ## Outputs
 
 ### `exit-code`
@@ -48,6 +61,20 @@ jobs:
         - 5432:5432
         options: --health-cmd pg_isready --health-interval 10s 
--health-timeout 5s --health-retries 5
 
+      smtp:
+        image: maildev/maildev:2.0.0-beta3
+        ports:
+          - 25:25
+        options: >-
+          --entrypoint=bin/maildev
+          --user=root
+          --health-cmd="sh -c \"[[ \$(wget -qO- http://smtp/healthz) == true 
]]\""
+          --
+          maildev/maildev:2.0.0-beta3
+          --smtp=25
+          --hide-extensions=STARTTLS
+          --web=80
+
     steps:
       - name: Checkout
         uses: actions/checkout@master
@@ -57,4 +84,5 @@ jobs:
         uses: ./.github/actions/to-integration-tests
         with:
           version: 5
+          smtp_address: localhost
 ```
diff --git a/.github/actions/to-integration-tests/action.yml 
b/.github/actions/to-integration-tests/action.yml
index 8c9d57f..63df76b 100644
--- a/.github/actions/to-integration-tests/action.yml
+++ b/.github/actions/to-integration-tests/action.yml
@@ -21,8 +21,20 @@ inputs:
   version:
     description: 'Version of Traffic Ops API against which to run tests, e.g. 
1, 2, 3, etc.'
     required: true
+    default: '3'
+  smtp_address:
+    description: 'Address of an SMTP server to use for the Traffic Ops API 
tests'
+    required: true
+  smtp_port:
+    description: 'Port of an SMTP server to use for the Traffic Ops API tests'
+    required: true
+    default: '25'
+  smtp_user:
+    description: 'The user to authenticate with for the SMTP server.'
+    required: false
+  smtp_password:
+    description: 'The user to authenticate with for the SMTP server.'
+    required: false
 runs:
-  using: 'docker'
-  image: 'Dockerfile'
-  args:
-    - ${{ inputs.version }}
+  using: 'node12'
+  main: 'dist/to-integration-tests.js'
diff --git a/.github/actions/to-integration-tests/cdn.json 
b/.github/actions/to-integration-tests/cdn.json
index efda921..890ade9 100644
--- a/.github/actions/to-integration-tests/cdn.json
+++ b/.github/actions/to-integration-tests/cdn.json
@@ -1,20 +1,20 @@
 {
-       "hypnotoad" : {
-               "listen" : [
+       "hypnotoad": {
+               "listen": [
                        
"https://not-a-real-host.test:1?cert=$PWD/localhost.crt&key=$PWD/localhost.key&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED";
                ],
-               "user" : "trafops",
-               "group" : "trafops",
-               "heartbeat_timeout" : 20,
-               "pid_file" : "/var/run/traffic_ops.pid",
-               "workers" : 12
+               "user": "trafops",
+               "group": "trafops",
+               "heartbeat_timeout": 20,
+               "pid_file": "/var/run/traffic_ops.pid",
+               "workers": 12
        },
        "use_ims": true,
-       "traffic_ops_golang" : {
+       "traffic_ops_golang": {
                "insecure": true,
-               "port" : "6443",
-               "log_location_error": "stderr",
-               "log_location_warning": "stderr",
+               "port": "6443",
+               "log_location_error": "error.log",
+               "log_location_warning": "warning.log",
                "log_location_info": null,
                "log_location_debug": null,
                "log_location_event": null,
@@ -23,29 +23,32 @@
                "db_query_timeout_seconds": 20,
                "supported_ds_metrics": [ "kbps", "tps_total", "tps_2xx", 
"tps_3xx", "tps_4xx", "tps_5xx" ]
        },
-       "cors" : {
-               "access_control_allow_origin" : "*"
+       "cors": {
+               "access_control_allow_origin": "*"
        },
-       "to" : {
-               "base_url" : "https://localhost";,
-               "email_from" : "[email protected]",
-               "no_account_found_msg" : "A Traffic Ops user account is 
required for access. Please contact your Traffic Ops user administrator."
+       "to": {
+               "base_url": "https://localhost";,
+               "email_from": "[email protected]",
+               "no_account_found_msg": "A Traffic Ops user account is required 
for access. Please contact your Traffic Ops user administrator."
        },
-       "portal" : {
-               "base_url" : "https://not-a-real-host.test/#!/";,
-               "email_from" : "[email protected]",
-               "pass_reset_path" : "user",
-               "user_register_path" : "user"
+       "portal": {
+               "base_url": "https://not-a-real-host.test/#!/";,
+               "email_from": "[email protected]",
+               "pass_reset_path": "user",
+               "user_register_path": "user"
        },
-       "secrets" : [
+       "secrets": [
                "blahblah"
        ],
-       "geniso" : {
-               "iso_root_path" : "/opt/traffic_ops/app/public"
+       "geniso": {
+               "iso_root_path": "/opt/traffic_ops/app/public"
        },
-       "inactivity_timeout" : 60,
-       "smtp" : {
-               "enabled" : false
+       "inactivity_timeout": 60,
+       "smtp": {
+               "enabled": true,
+               "user": "$INPUT_SMTP_USER",
+               "password": "$INPUT_SMTP_PASSWORD",
+               "address": "${INPUT_SMTP_ADDRESS}:${INPUT_SMTP_PORT}"
        },
        "InfluxEnabled": false
 }
diff --git a/.github/actions/to-integration-tests/database.json 
b/.github/actions/to-integration-tests/database.json
index 8d08eb4..778be80 100644
--- a/.github/actions/to-integration-tests/database.json
+++ b/.github/actions/to-integration-tests/database.json
@@ -1,7 +1,7 @@
 {
        "description": "Local PostgreSQL database on port 5432",
        "dbname": "traffic_ops",
-       "hostname": "postgres",
+       "hostname": "172.17.0.1",
        "user": "traffic_ops",
        "password": "twelve",
        "port": "5432",
diff --git a/.github/actions/to-integration-tests/dbconf.yml 
b/.github/actions/to-integration-tests/dbconf.yml
index f565670..3078589 100644
--- a/.github/actions/to-integration-tests/dbconf.yml
+++ b/.github/actions/to-integration-tests/dbconf.yml
@@ -19,5 +19,5 @@ name: dbconf.yml
 
 test:
   driver: postgres
-  open: host=postgres port=5432 user=traffic_ops password=twelve 
dbname=traffic_ops sslmode=disable
+  open: host=172.17.0.1 port=5432 user=traffic_ops password=twelve 
dbname=traffic_ops sslmode=disable
 
diff --git a/.github/actions/to-integration-tests/dist/to-integration-tests.js 
b/.github/actions/to-integration-tests/dist/to-integration-tests.js
new file mode 100644
index 0000000..6d1f833
--- /dev/null
+++ b/.github/actions/to-integration-tests/dist/to-integration-tests.js
@@ -0,0 +1,31 @@
+/*
+* 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.
+*/
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+    return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const child_process_1 = __importDefault(require("child_process"));
+const path_1 = __importDefault(require("path"));
+const spawnOptions = { stdio: "inherit" };
+function runProcess(...commandArguments) {
+    console.info(...commandArguments);
+    const { status } = child_process_1.default.spawnSync(commandArguments[0], 
commandArguments.slice(1), spawnOptions);
+    if (status === 0) {
+        return;
+    }
+    console.error("Child process \"", ...commandArguments, "\" exited with 
status code", status, "!");
+    process.exit(status !== null && status !== void 0 ? status : 1);
+}
+runProcess(path_1.default.join(__dirname, "../entrypoint.sh"));
diff --git a/.github/actions/to-integration-tests/entrypoint.sh 
b/.github/actions/to-integration-tests/entrypoint.sh
index 8fae324..d3c4ff2 100755
--- a/.github/actions/to-integration-tests/entrypoint.sh
+++ b/.github/actions/to-integration-tests/entrypoint.sh
@@ -1,4 +1,4 @@
-#!/bin/sh -l
+#!/bin/bash
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -17,15 +17,90 @@
 # under the License.
 
 download_go() {
+       . build/functions.sh
+       if verify_and_set_go_version; then
+               return
+       fi
        go_version="$(cat "${GITHUB_WORKSPACE}/GO_VERSION")"
        wget -O go.tar.gz 
"https://dl.google.com/go/go${go_version}.linux-amd64.tar.gz";
-       tar -C /usr/local -xzf go.tar.gz
+       echo "Extracting Go ${go_version}..."
+       <<-'SUDO_COMMANDS' sudo sh
+               set -o errexit
+               go_dir="$(
+                       dirname "$(
+                               dirname "$(
+                                       realpath "$(
+                                               which go
+                                               )")")")"
+               mv "$go_dir" "${go_dir}.unused"
+               tar -C /usr/local -xzf go.tar.gz
+       SUDO_COMMANDS
        rm go.tar.gz
-       export PATH="${PATH}:${GOROOT}/bin"
        go version
 }
-download_go
 
+gray_bg="$(printf '%s%s' $'\x1B' '[100m')";
+red_bg="$(printf '%s%s' $'\x1B' '[41m')";
+yellow_bg="$(printf '%s%s' $'\x1B' '[43m')";
+black_fg="$(printf '%s%s' $'\x1B' '[30m')";
+color_and_prefix() {
+       color="$1";
+       shift;
+       prefix="$1";
+       normal_bg="$(printf '%s%s' $'\x1B' '[49m')";
+       normal_fg="$(printf '%s%s' $'\x1B' '[39m')";
+       sed "s/^/${color}${black_fg}${prefix}: /" | sed 
"s/$/${normal_bg}${normal_fg}/";
+}
+
+ciab_dir="${GITHUB_WORKSPACE}/infrastructure/cdn-in-a-box";
+trafficvault=trafficvault;
+start_traffic_vault() {
+       <<-'/ETC/HOSTS' sudo tee --append /etc/hosts
+               172.17.0.1    trafficvault.infra.ciab.test
+       /ETC/HOSTS
+
+       <<-'BASH_LINES' cat 
>infrastructure/cdn-in-a-box/traffic_vault/prestart.d/00-0-standalone-config.sh;
+               TV_FQDN="${TV_HOST}.${INFRA_SUBDOMAIN}.${TLD_DOMAIN}" # Also 
used in 02-add-search-schema.sh
+               certs_dir=/etc/ssl/certs;
+               X509_INFRA_CERT_FILE="${certs_dir}/trafficvault.crt";
+               X509_INFRA_KEY_FILE="${certs_dir}/trafficvault.key";
+
+               # Generate x509 certificate
+               openssl req -new -x509 -nodes -newkey rsa:4096 -out 
"$X509_INFRA_CERT_FILE" -keyout "$X509_INFRA_KEY_FILE" -subj "/CN=${TV_FQDN}";
+
+               # Do not wait for CDN in a Box to generate SSL keys
+               sed -i '0,/^update-ca-certificates/d' 
/etc/riak/prestart.d/00-config.sh;
+
+               # Do not try to source to-access.sh
+               sed -i '/to-access\.sh/d' /etc/riak/{prestart.d,poststart.d}/*
+       BASH_LINES
+
+       DOCKER_BUILDKIT=1 docker build "$ciab_dir" -f 
"${ciab_dir}/traffic_vault/Dockerfile" -t "$trafficvault" 2>&1 |
+               color_and_prefix "$gray_bg" "building Traffic Vault";
+       if [[ "$INPUT_VERSION" -lt 3 ]]; then
+               echo 'Not starting Traffic Vault for API versions less than 3'
+               return;
+       fi;
+       echo 'Starting Traffic Vault...';
+       docker run \
+               --detach \
+               --env-file="${ciab_dir}/variables.env" \
+               --hostname="${trafficvault}.infra.ciab.test" \
+               --name="$trafficvault" \
+               --publish=8087:8087 \
+               --rm \
+               "$trafficvault" \
+               /usr/lib/riak/riak-cluster.sh;
+       docker logs -f "$trafficvault" 2>&1 |
+               color_and_prefix "$gray_bg" 'Traffic Vault';
+}
+start_traffic_vault &
+
+sudo apt-get install -y --no-install-recommends gettext
+
+GOROOT=/usr/local/go
+export GOROOT PATH="${PATH}:${GOROOT}/bin"
+download_go
 export GOPATH="$(mktemp -d)"
 srcdir="$GOPATH/src/github.com/apache"
 mkdir -p "$srcdir"
@@ -34,8 +109,8 @@ ln -s "$PWD" "$srcdir/trafficcontrol"
 cd "$srcdir/trafficcontrol/traffic_ops/traffic_ops_golang"
 
 
-/usr/local/go/bin/go get ./...
-/usr/local/go/bin/go build .
+go get ./...
+go build .
 
 echo "
 -----BEGIN CERTIFICATE-----
@@ -91,31 +166,33 @@ A22D22wvfs7CE3cUz/8UnvLM3kbTTu1WbbBbrHjAV47sAHjW/ckTqeo=
 -----END RSA PRIVATE KEY-----
 " > localhost.key
 
-envsubst </cdn.json >cdn.conf
-mv /database.json ./database.conf
+resources="$(dirname "$0")"
+envsubst <"${resources}/cdn.json" >cdn.conf
+cp "${resources}/database.json" database.conf
 
-./traffic_ops_golang --cfg ./cdn.conf --dbcfg ./database.conf >out.log 
2>err.log &
+export $(<"${ciab_dir}/variables.env" sed '/^#/d') # defines 
TV_ADMIN_USER/PASSWORD
+envsubst <"${resources}/riak.json" >riak.conf
 
-if [ -z "$INPUT_VERSION" ]; then
-       INPUT_VERSION="3";
-fi
+truncate --size=0 warning.log error.log # Removes output from previous API 
versions and makes sure files exist
+./traffic_ops_golang --cfg ./cdn.conf --dbcfg ./database.conf -riakcfg 
riak.conf &
 
-cd "../testing/api/v$INPUT_VERSION"
+# TODO - Make these logs build artifacts
+# 2>&1 makes terminal output go faster, even though stderr will not contain 
anything
+tail -f warning.log 2>&1 | color_and_prefix "${yellow_bg}" 'Traffic Ops' &
+tail -f error.log 2>&1 | color_and_prefix "${red_bg}" 'Traffic Ops' &
 
-cp /traffic-ops-test.json ./traffic-ops-test.conf
-/usr/local/go/bin/go test -v --cfg ./traffic-ops-test.conf
-CODE="$?"
-rm traffic-ops-test.conf
 
-# TODO - make these build artifacts
-if [ -f ../../../traffic_ops_golang/out.log ]; then
-       cat ../../../traffic_ops_golang/out.log
-       rm ../.../../traffic_ops_golang/out.log
-fi
+cd "../testing/api/v$INPUT_VERSION"
 
-if [ -f ../../../traffic_ops_golang/err.log ]; then
-       cat ../../../traffic_ops_golang/err.log >&2
-       rm ../../../traffic_ops_golang/err.log
-fi
+cp "${resources}/traffic-ops-test.json" traffic-ops-test.conf
+go test -test.v --cfg traffic-ops-test.conf
+CODE=$?
+rm traffic-ops-test.conf
+if [[ "$INPUT_VERSION" -ge 3 ]]; then
+       echo 'Stopping Traffic Vault...'
+       docker kill "$trafficvault";
+fi;
+echo 'Killing background jobs...';
+kill -9 $(jobs -p);
 
 exit "$CODE"
diff --git a/.github/actions/to-integration-tests/package-lock.json 
b/.github/actions/to-integration-tests/package-lock.json
new file mode 100644
index 0000000..2184aeb
--- /dev/null
+++ b/.github/actions/to-integration-tests/package-lock.json
@@ -0,0 +1,1994 @@
+{
+    "name": "to-integration-tests",
+    "version": "0.0.0",
+    "lockfileVersion": 1,
+    "requires": true,
+    "dependencies": {
+        "@babel/code-frame": {
+            "version": "7.10.4",
+            "resolved": 
"https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz";,
+            "integrity": 
"sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+            "dev": true,
+            "requires": {
+                "@babel/highlight": "^7.10.4"
+            }
+        },
+        "@babel/helper-validator-identifier": {
+            "version": "7.10.4",
+            "resolved": 
"https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz";,
+            "integrity": 
"sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+            "dev": true
+        },
+        "@babel/highlight": {
+            "version": "7.10.4",
+            "resolved": 
"https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz";,
+            "integrity": 
"sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-validator-identifier": "^7.10.4",
+                "chalk": "^2.0.0",
+                "js-tokens": "^4.0.0"
+            },
+            "dependencies": {
+                "chalk": {
+                    "version": "2.4.2",
+                    "resolved": 
"https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz";,
+                    "integrity": 
"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+                    "dev": true,
+                    "requires": {
+                        "ansi-styles": "^3.2.1",
+                        "escape-string-regexp": "^1.0.5",
+                        "supports-color": "^5.3.0"
+                    }
+                }
+            }
+        },
+        "@eslint/eslintrc": {
+            "version": "0.1.3",
+            "resolved": 
"https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz";,
+            "integrity": 
"sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==",
+            "dev": true,
+            "requires": {
+                "ajv": "^6.12.4",
+                "debug": "^4.1.1",
+                "espree": "^7.3.0",
+                "globals": "^12.1.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.2.1",
+                "js-yaml": "^3.13.1",
+                "lodash": "^4.17.19",
+                "minimatch": "^3.0.4",
+                "strip-json-comments": "^3.1.1"
+            },
+            "dependencies": {
+                "ignore": {
+                    "version": "4.0.6",
+                    "resolved": 
"https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz";,
+                    "integrity": 
"sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+                    "dev": true
+                }
+            }
+        },
+        "@nodelib/fs.scandir": {
+            "version": "2.1.3",
+            "resolved": 
"https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz";,
+            "integrity": 
"sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==",
+            "dev": true,
+            "requires": {
+                "@nodelib/fs.stat": "2.0.3",
+                "run-parallel": "^1.1.9"
+            }
+        },
+        "@nodelib/fs.stat": {
+            "version": "2.0.3",
+            "resolved": 
"https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz";,
+            "integrity": 
"sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
+            "dev": true
+        },
+        "@nodelib/fs.walk": {
+            "version": "1.2.4",
+            "resolved": 
"https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz";,
+            "integrity": 
"sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==",
+            "dev": true,
+            "requires": {
+                "@nodelib/fs.scandir": "2.1.3",
+                "fastq": "^1.6.0"
+            }
+        },
+        "@types/json-schema": {
+            "version": "7.0.6",
+            "resolved": 
"https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz";,
+            "integrity": 
"sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==",
+            "dev": true
+        },
+        "@types/json5": {
+            "version": "0.0.29",
+            "resolved": 
"https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz";,
+            "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
+            "dev": true
+        },
+        "@types/node": {
+            "version": "14.14.0",
+            "resolved": 
"https://registry.npmjs.org/@types/node/-/node-14.14.0.tgz";,
+            "integrity": 
"sha512-BfbIHP9IapdupGhq/hc+jT5dyiBVZ2DdeC5WwJWQWDb0GijQlzUFAeIQn/2GtvZcd2HVUU7An8felIICFTC2qg==",
+            "dev": true
+        },
+        "@typescript-eslint/eslint-plugin": {
+            "version": "4.5.0",
+            "resolved": 
"https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.5.0.tgz";,
+            "integrity": 
"sha512-mjb/gwNcmDKNt+6mb7Aj/TjKzIJjOPcoCJpjBQC9ZnTRnBt1p4q5dJSSmIqAtsZ/Pff5N+hJlbiPc5bl6QN4OQ==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/experimental-utils": "4.5.0",
+                "@typescript-eslint/scope-manager": "4.5.0",
+                "debug": "^4.1.1",
+                "functional-red-black-tree": "^1.0.1",
+                "regexpp": "^3.0.0",
+                "semver": "^7.3.2",
+                "tsutils": "^3.17.1"
+            }
+        },
+        "@typescript-eslint/eslint-plugin-tslint": {
+            "version": "4.6.0",
+            "resolved": 
"https://registry.npmjs.org/@typescript-eslint/eslint-plugin-tslint/-/eslint-plugin-tslint-4.6.0.tgz";,
+            "integrity": 
"sha512-3ba/AAcufH6Gd2UB4Qzsx0PoxzALiad5sulv82kshNJju1bWcvFa3EKdleGwBjEkaK8pvo1bE3n4wZFP2p6Y3g==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/experimental-utils": "4.6.0",
+                "lodash": "^4.17.15"
+            },
+            "dependencies": {
+                "@typescript-eslint/experimental-utils": {
+                    "version": "4.6.0",
+                    "resolved": 
"https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.0.tgz";,
+                    "integrity": 
"sha512-pnh6Beh2/4xjJVNL+keP49DFHk3orDHHFylSp3WEjtgW3y1U+6l+jNnJrGlbs6qhAz5z96aFmmbUyKhunXKvKw==",
+                    "dev": true,
+                    "requires": {
+                        "@types/json-schema": "^7.0.3",
+                        "@typescript-eslint/scope-manager": "4.6.0",
+                        "@typescript-eslint/types": "4.6.0",
+                        "@typescript-eslint/typescript-estree": "4.6.0",
+                        "eslint-scope": "^5.0.0",
+                        "eslint-utils": "^2.0.0"
+                    }
+                },
+                "@typescript-eslint/scope-manager": {
+                    "version": "4.6.0",
+                    "resolved": 
"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.6.0.tgz";,
+                    "integrity": 
"sha512-uZx5KvStXP/lwrMrfQQwDNvh2ppiXzz5TmyTVHb+5TfZ3sUP7U1onlz3pjoWrK9konRyFe1czyxObWTly27Ang==",
+                    "dev": true,
+                    "requires": {
+                        "@typescript-eslint/types": "4.6.0",
+                        "@typescript-eslint/visitor-keys": "4.6.0"
+                    }
+                },
+                "@typescript-eslint/types": {
+                    "version": "4.6.0",
+                    "resolved": 
"https://registry.npmjs.org/@typescript-eslint/types/-/types-4.6.0.tgz";,
+                    "integrity": 
"sha512-5FAgjqH68SfFG4UTtIFv+rqYJg0nLjfkjD0iv+5O27a0xEeNZ5rZNDvFGZDizlCD1Ifj7MAbSW2DPMrf0E9zjA==",
+                    "dev": true
+                },
+                "@typescript-eslint/typescript-estree": {
+                    "version": "4.6.0",
+                    "resolved": 
"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.0.tgz";,
+                    "integrity": 
"sha512-s4Z9qubMrAo/tw0CbN0IN4AtfwuehGXVZM0CHNMdfYMGBDhPdwTEpBrecwhP7dRJu6d9tT9ECYNaWDHvlFSngA==",
+                    "dev": true,
+                    "requires": {
+                        "@typescript-eslint/types": "4.6.0",
+                        "@typescript-eslint/visitor-keys": "4.6.0",
+                        "debug": "^4.1.1",
+                        "globby": "^11.0.1",
+                        "is-glob": "^4.0.1",
+                        "lodash": "^4.17.15",
+                        "semver": "^7.3.2",
+                        "tsutils": "^3.17.1"
+                    }
+                },
+                "@typescript-eslint/visitor-keys": {
+                    "version": "4.6.0",
+                    "resolved": 
"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.0.tgz";,
+                    "integrity": 
"sha512-38Aa9Ztl0XyFPVzmutHXqDMCu15Xx8yKvUo38Gu3GhsuckCh3StPI5t2WIO9LHEsOH7MLmlGfKUisU8eW1Sjhg==",
+                    "dev": true,
+                    "requires": {
+                        "@typescript-eslint/types": "4.6.0",
+                        "eslint-visitor-keys": "^2.0.0"
+                    }
+                }
+            }
+        },
+        "@typescript-eslint/experimental-utils": {
+            "version": "4.5.0",
+            "resolved": 
"https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.5.0.tgz";,
+            "integrity": 
"sha512-bW9IpSAKYvkqDGRZzayBXIgPsj2xmmVHLJ+flGSoN0fF98pGoKFhbunIol0VF2Crka7z984EEhFi623Rl7e6gg==",
+            "dev": true,
+            "requires": {
+                "@types/json-schema": "^7.0.3",
+                "@typescript-eslint/scope-manager": "4.5.0",
+                "@typescript-eslint/types": "4.5.0",
+                "@typescript-eslint/typescript-estree": "4.5.0",
+                "eslint-scope": "^5.0.0",
+                "eslint-utils": "^2.0.0"
+            }
+        },
+        "@typescript-eslint/parser": {
+            "version": "4.5.0",
+            "resolved": 
"https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.5.0.tgz";,
+            "integrity": 
"sha512-xb+gmyhQcnDWe+5+xxaQk5iCw6KqXd8VQxGiTeELTMoYeRjpocZYYRP1gFVM2C8Yl0SpUvLa1lhprwqZ00w3Iw==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/scope-manager": "4.5.0",
+                "@typescript-eslint/types": "4.5.0",
+                "@typescript-eslint/typescript-estree": "4.5.0",
+                "debug": "^4.1.1"
+            }
+        },
+        "@typescript-eslint/scope-manager": {
+            "version": "4.5.0",
+            "resolved": 
"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.5.0.tgz";,
+            "integrity": 
"sha512-C0cEO0cTMPJ/w4RA/KVe4LFFkkSh9VHoFzKmyaaDWAnPYIEzVCtJ+Un8GZoJhcvq+mPFXEsXa01lcZDHDG6Www==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/types": "4.5.0",
+                "@typescript-eslint/visitor-keys": "4.5.0"
+            }
+        },
+        "@typescript-eslint/types": {
+            "version": "4.5.0",
+            "resolved": 
"https://registry.npmjs.org/@typescript-eslint/types/-/types-4.5.0.tgz";,
+            "integrity": 
"sha512-n2uQoXnyWNk0Les9MtF0gCK3JiWd987JQi97dMSxBOzVoLZXCNtxFckVqt1h8xuI1ix01t+iMY4h4rFMj/303g==",
+            "dev": true
+        },
+        "@typescript-eslint/typescript-estree": {
+            "version": "4.5.0",
+            "resolved": 
"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.5.0.tgz";,
+            "integrity": 
"sha512-gN1mffq3zwRAjlYWzb5DanarOPdajQwx5MEWkWCk0XvqC8JpafDTeioDoow2L4CA/RkYZu7xEsGZRhqrTsAG8w==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/types": "4.5.0",
+                "@typescript-eslint/visitor-keys": "4.5.0",
+                "debug": "^4.1.1",
+                "globby": "^11.0.1",
+                "is-glob": "^4.0.1",
+                "lodash": "^4.17.15",
+                "semver": "^7.3.2",
+                "tsutils": "^3.17.1"
+            }
+        },
+        "@typescript-eslint/visitor-keys": {
+            "version": "4.5.0",
+            "resolved": 
"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.5.0.tgz";,
+            "integrity": 
"sha512-UHq4FSa55NDZqscRU//O5ROFhHa9Hqn9KWTEvJGTArtTQp5GKv9Zqf6d/Q3YXXcFv4woyBml7fJQlQ+OuqRcHA==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/types": "4.5.0",
+                "eslint-visitor-keys": "^2.0.0"
+            }
+        },
+        "acorn": {
+            "version": "7.4.1",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz";,
+            "integrity": 
"sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+            "dev": true
+        },
+        "acorn-jsx": {
+            "version": "5.3.1",
+            "resolved": 
"https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz";,
+            "integrity": 
"sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
+            "dev": true
+        },
+        "ajv": {
+            "version": "6.12.6",
+            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz";,
+            "integrity": 
"sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+            "dev": true,
+            "requires": {
+                "fast-deep-equal": "^3.1.1",
+                "fast-json-stable-stringify": "^2.0.0",
+                "json-schema-traverse": "^0.4.1",
+                "uri-js": "^4.2.2"
+            }
+        },
+        "ansi-colors": {
+            "version": "4.1.1",
+            "resolved": 
"https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz";,
+            "integrity": 
"sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+            "dev": true
+        },
+        "ansi-regex": {
+            "version": "5.0.0",
+            "resolved": 
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz";,
+            "integrity": 
"sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+            "dev": true
+        },
+        "ansi-styles": {
+            "version": "3.2.1",
+            "resolved": 
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz";,
+            "integrity": 
"sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+            "dev": true,
+            "requires": {
+                "color-convert": "^1.9.0"
+            }
+        },
+        "argparse": {
+            "version": "1.0.10",
+            "resolved": 
"https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz";,
+            "integrity": 
"sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+            "dev": true,
+            "requires": {
+                "sprintf-js": "~1.0.2"
+            }
+        },
+        "array-includes": {
+            "version": "3.1.1",
+            "resolved": 
"https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz";,
+            "integrity": 
"sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.3",
+                "es-abstract": "^1.17.0",
+                "is-string": "^1.0.5"
+            }
+        },
+        "array-union": {
+            "version": "2.1.0",
+            "resolved": 
"https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz";,
+            "integrity": 
"sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+            "dev": true
+        },
+        "array.prototype.flat": {
+            "version": "1.2.3",
+            "resolved": 
"https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz";,
+            "integrity": 
"sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.3",
+                "es-abstract": "^1.17.0-next.1"
+            }
+        },
+        "astral-regex": {
+            "version": "1.0.0",
+            "resolved": 
"https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz";,
+            "integrity": 
"sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+            "dev": true
+        },
+        "balanced-match": {
+            "version": "1.0.0",
+            "resolved": 
"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz";,
+            "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+            "dev": true
+        },
+        "brace-expansion": {
+            "version": "1.1.11",
+            "resolved": 
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz";,
+            "integrity": 
"sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "dev": true,
+            "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "braces": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz";,
+            "integrity": 
"sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+            "dev": true,
+            "requires": {
+                "fill-range": "^7.0.1"
+            }
+        },
+        "builtin-modules": {
+            "version": "1.1.1",
+            "resolved": 
"https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz";,
+            "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+            "dev": true
+        },
+        "callsites": {
+            "version": "3.1.0",
+            "resolved": 
"https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz";,
+            "integrity": 
"sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+            "dev": true
+        },
+        "chalk": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz";,
+            "integrity": 
"sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+            "dev": true,
+            "requires": {
+                "ansi-styles": "^4.1.0",
+                "supports-color": "^7.1.0"
+            },
+            "dependencies": {
+                "ansi-styles": {
+                    "version": "4.3.0",
+                    "resolved": 
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz";,
+                    "integrity": 
"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+                    "dev": true,
+                    "requires": {
+                        "color-convert": "^2.0.1"
+                    }
+                },
+                "color-convert": {
+                    "version": "2.0.1",
+                    "resolved": 
"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz";,
+                    "integrity": 
"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+                    "dev": true,
+                    "requires": {
+                        "color-name": "~1.1.4"
+                    }
+                },
+                "color-name": {
+                    "version": "1.1.4",
+                    "resolved": 
"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz";,
+                    "integrity": 
"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+                    "dev": true
+                },
+                "has-flag": {
+                    "version": "4.0.0",
+                    "resolved": 
"https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz";,
+                    "integrity": 
"sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+                    "dev": true
+                },
+                "supports-color": {
+                    "version": "7.2.0",
+                    "resolved": 
"https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz";,
+                    "integrity": 
"sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+                    "dev": true,
+                    "requires": {
+                        "has-flag": "^4.0.0"
+                    }
+                }
+            }
+        },
+        "color-convert": {
+            "version": "1.9.3",
+            "resolved": 
"https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz";,
+            "integrity": 
"sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+            "dev": true,
+            "requires": {
+                "color-name": "1.1.3"
+            }
+        },
+        "color-name": {
+            "version": "1.1.3",
+            "resolved": 
"https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz";,
+            "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+            "dev": true
+        },
+        "commander": {
+            "version": "2.20.3",
+            "resolved": 
"https://registry.npmjs.org/commander/-/commander-2.20.3.tgz";,
+            "integrity": 
"sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+            "dev": true
+        },
+        "comment-parser": {
+            "version": "0.7.6",
+            "resolved": 
"https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.6.tgz";,
+            "integrity": 
"sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg==",
+            "dev": true
+        },
+        "concat-map": {
+            "version": "0.0.1",
+            "resolved": 
"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz";,
+            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+            "dev": true
+        },
+        "contains-path": {
+            "version": "0.1.0",
+            "resolved": 
"https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz";,
+            "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
+            "dev": true
+        },
+        "cross-spawn": {
+            "version": "7.0.3",
+            "resolved": 
"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz";,
+            "integrity": 
"sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+            "dev": true,
+            "requires": {
+                "path-key": "^3.1.0",
+                "shebang-command": "^2.0.0",
+                "which": "^2.0.1"
+            }
+        },
+        "debug": {
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz";,
+            "integrity": 
"sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+            "dev": true,
+            "requires": {
+                "ms": "2.1.2"
+            }
+        },
+        "deep-is": {
+            "version": "0.1.3",
+            "resolved": 
"https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz";,
+            "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+            "dev": true
+        },
+        "define-properties": {
+            "version": "1.1.3",
+            "resolved": 
"https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz";,
+            "integrity": 
"sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+            "dev": true,
+            "requires": {
+                "object-keys": "^1.0.12"
+            }
+        },
+        "diff": {
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz";,
+            "integrity": 
"sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+            "dev": true
+        },
+        "dir-glob": {
+            "version": "3.0.1",
+            "resolved": 
"https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz";,
+            "integrity": 
"sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+            "dev": true,
+            "requires": {
+                "path-type": "^4.0.0"
+            }
+        },
+        "doctrine": {
+            "version": "3.0.0",
+            "resolved": 
"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz";,
+            "integrity": 
"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+            "dev": true,
+            "requires": {
+                "esutils": "^2.0.2"
+            }
+        },
+        "emoji-regex": {
+            "version": "7.0.3",
+            "resolved": 
"https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz";,
+            "integrity": 
"sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+            "dev": true
+        },
+        "enquirer": {
+            "version": "2.3.6",
+            "resolved": 
"https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz";,
+            "integrity": 
"sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+            "dev": true,
+            "requires": {
+                "ansi-colors": "^4.1.1"
+            }
+        },
+        "error-ex": {
+            "version": "1.3.2",
+            "resolved": 
"https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz";,
+            "integrity": 
"sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+            "dev": true,
+            "requires": {
+                "is-arrayish": "^0.2.1"
+            }
+        },
+        "es-abstract": {
+            "version": "1.17.7",
+            "resolved": 
"https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz";,
+            "integrity": 
"sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
+            "dev": true,
+            "requires": {
+                "es-to-primitive": "^1.2.1",
+                "function-bind": "^1.1.1",
+                "has": "^1.0.3",
+                "has-symbols": "^1.0.1",
+                "is-callable": "^1.2.2",
+                "is-regex": "^1.1.1",
+                "object-inspect": "^1.8.0",
+                "object-keys": "^1.1.1",
+                "object.assign": "^4.1.1",
+                "string.prototype.trimend": "^1.0.1",
+                "string.prototype.trimstart": "^1.0.1"
+            }
+        },
+        "es-to-primitive": {
+            "version": "1.2.1",
+            "resolved": 
"https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz";,
+            "integrity": 
"sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+            "dev": true,
+            "requires": {
+                "is-callable": "^1.1.4",
+                "is-date-object": "^1.0.1",
+                "is-symbol": "^1.0.2"
+            }
+        },
+        "escape-string-regexp": {
+            "version": "1.0.5",
+            "resolved": 
"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz";,
+            "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+            "dev": true
+        },
+        "eslint": {
+            "version": "7.11.0",
+            "resolved": 
"https://registry.npmjs.org/eslint/-/eslint-7.11.0.tgz";,
+            "integrity": 
"sha512-G9+qtYVCHaDi1ZuWzBsOWo2wSwd70TXnU6UHA3cTYHp7gCTXZcpggWFoUVAMRarg68qtPoNfFbzPh+VdOgmwmw==",
+            "dev": true,
+            "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "@eslint/eslintrc": "^0.1.3",
+                "ajv": "^6.10.0",
+                "chalk": "^4.0.0",
+                "cross-spawn": "^7.0.2",
+                "debug": "^4.0.1",
+                "doctrine": "^3.0.0",
+                "enquirer": "^2.3.5",
+                "eslint-scope": "^5.1.1",
+                "eslint-utils": "^2.1.0",
+                "eslint-visitor-keys": "^2.0.0",
+                "espree": "^7.3.0",
+                "esquery": "^1.2.0",
+                "esutils": "^2.0.2",
+                "file-entry-cache": "^5.0.1",
+                "functional-red-black-tree": "^1.0.1",
+                "glob-parent": "^5.0.0",
+                "globals": "^12.1.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.0.0",
+                "imurmurhash": "^0.1.4",
+                "is-glob": "^4.0.0",
+                "js-yaml": "^3.13.1",
+                "json-stable-stringify-without-jsonify": "^1.0.1",
+                "levn": "^0.4.1",
+                "lodash": "^4.17.19",
+                "minimatch": "^3.0.4",
+                "natural-compare": "^1.4.0",
+                "optionator": "^0.9.1",
+                "progress": "^2.0.0",
+                "regexpp": "^3.1.0",
+                "semver": "^7.2.1",
+                "strip-ansi": "^6.0.0",
+                "strip-json-comments": "^3.1.0",
+                "table": "^5.2.3",
+                "text-table": "^0.2.0",
+                "v8-compile-cache": "^2.0.3"
+            },
+            "dependencies": {
+                "ignore": {
+                    "version": "4.0.6",
+                    "resolved": 
"https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz";,
+                    "integrity": 
"sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+                    "dev": true
+                }
+            }
+        },
+        "eslint-import-resolver-node": {
+            "version": "0.3.4",
+            "resolved": 
"https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz";,
+            "integrity": 
"sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==",
+            "dev": true,
+            "requires": {
+                "debug": "^2.6.9",
+                "resolve": "^1.13.1"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": 
"https://registry.npmjs.org/debug/-/debug-2.6.9.tgz";,
+                    "integrity": 
"sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "ms": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz";,
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "dev": true
+                }
+            }
+        },
+        "eslint-module-utils": {
+            "version": "2.6.0",
+            "resolved": 
"https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz";,
+            "integrity": 
"sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==",
+            "dev": true,
+            "requires": {
+                "debug": "^2.6.9",
+                "pkg-dir": "^2.0.0"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": 
"https://registry.npmjs.org/debug/-/debug-2.6.9.tgz";,
+                    "integrity": 
"sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "ms": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz";,
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "dev": true
+                }
+            }
+        },
+        "eslint-plugin-import": {
+            "version": "2.22.1",
+            "resolved": 
"https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz";,
+            "integrity": 
"sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==",
+            "dev": true,
+            "requires": {
+                "array-includes": "^3.1.1",
+                "array.prototype.flat": "^1.2.3",
+                "contains-path": "^0.1.0",
+                "debug": "^2.6.9",
+                "doctrine": "1.5.0",
+                "eslint-import-resolver-node": "^0.3.4",
+                "eslint-module-utils": "^2.6.0",
+                "has": "^1.0.3",
+                "minimatch": "^3.0.4",
+                "object.values": "^1.1.1",
+                "read-pkg-up": "^2.0.0",
+                "resolve": "^1.17.0",
+                "tsconfig-paths": "^3.9.0"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": 
"https://registry.npmjs.org/debug/-/debug-2.6.9.tgz";,
+                    "integrity": 
"sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "doctrine": {
+                    "version": "1.5.0",
+                    "resolved": 
"https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz";,
+                    "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
+                    "dev": true,
+                    "requires": {
+                        "esutils": "^2.0.2",
+                        "isarray": "^1.0.0"
+                    }
+                },
+                "ms": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz";,
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "dev": true
+                }
+            }
+        },
+        "eslint-plugin-jsdoc": {
+            "version": "30.7.3",
+            "resolved": 
"https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-30.7.3.tgz";,
+            "integrity": 
"sha512-slzJeKrm3vXabRYcFBpbUgWgdnATN9rNOFAr7IhmkxmR9Vk/6qN1c/IdvTqVSEctDRQ08chR+Lvk8fRayXgYZg==",
+            "dev": true,
+            "requires": {
+                "comment-parser": "^0.7.6",
+                "debug": "^4.2.0",
+                "jsdoctypeparser": "^9.0.0",
+                "lodash": "^4.17.20",
+                "regextras": "^0.7.1",
+                "semver": "^7.3.2",
+                "spdx-expression-parse": "^3.0.1"
+            }
+        },
+        "eslint-scope": {
+            "version": "5.1.1",
+            "resolved": 
"https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz";,
+            "integrity": 
"sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+            "dev": true,
+            "requires": {
+                "esrecurse": "^4.3.0",
+                "estraverse": "^4.1.1"
+            }
+        },
+        "eslint-utils": {
+            "version": "2.1.0",
+            "resolved": 
"https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz";,
+            "integrity": 
"sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+            "dev": true,
+            "requires": {
+                "eslint-visitor-keys": "^1.1.0"
+            },
+            "dependencies": {
+                "eslint-visitor-keys": {
+                    "version": "1.3.0",
+                    "resolved": 
"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz";,
+                    "integrity": 
"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+                    "dev": true
+                }
+            }
+        },
+        "eslint-visitor-keys": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz";,
+            "integrity": 
"sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+            "dev": true
+        },
+        "espree": {
+            "version": "7.3.0",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz";,
+            "integrity": 
"sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
+            "dev": true,
+            "requires": {
+                "acorn": "^7.4.0",
+                "acorn-jsx": "^5.2.0",
+                "eslint-visitor-keys": "^1.3.0"
+            },
+            "dependencies": {
+                "eslint-visitor-keys": {
+                    "version": "1.3.0",
+                    "resolved": 
"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz";,
+                    "integrity": 
"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+                    "dev": true
+                }
+            }
+        },
+        "esprima": {
+            "version": "4.0.1",
+            "resolved": 
"https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz";,
+            "integrity": 
"sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+            "dev": true
+        },
+        "esquery": {
+            "version": "1.3.1",
+            "resolved": 
"https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz";,
+            "integrity": 
"sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
+            "dev": true,
+            "requires": {
+                "estraverse": "^5.1.0"
+            },
+            "dependencies": {
+                "estraverse": {
+                    "version": "5.2.0",
+                    "resolved": 
"https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz";,
+                    "integrity": 
"sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+                    "dev": true
+                }
+            }
+        },
+        "esrecurse": {
+            "version": "4.3.0",
+            "resolved": 
"https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz";,
+            "integrity": 
"sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+            "dev": true,
+            "requires": {
+                "estraverse": "^5.2.0"
+            },
+            "dependencies": {
+                "estraverse": {
+                    "version": "5.2.0",
+                    "resolved": 
"https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz";,
+                    "integrity": 
"sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+                    "dev": true
+                }
+            }
+        },
+        "estraverse": {
+            "version": "4.3.0",
+            "resolved": 
"https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz";,
+            "integrity": 
"sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+            "dev": true
+        },
+        "esutils": {
+            "version": "2.0.3",
+            "resolved": 
"https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz";,
+            "integrity": 
"sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+            "dev": true
+        },
+        "fast-deep-equal": {
+            "version": "3.1.3",
+            "resolved": 
"https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz";,
+            "integrity": 
"sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+            "dev": true
+        },
+        "fast-glob": {
+            "version": "3.2.4",
+            "resolved": 
"https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz";,
+            "integrity": 
"sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==",
+            "dev": true,
+            "requires": {
+                "@nodelib/fs.stat": "^2.0.2",
+                "@nodelib/fs.walk": "^1.2.3",
+                "glob-parent": "^5.1.0",
+                "merge2": "^1.3.0",
+                "micromatch": "^4.0.2",
+                "picomatch": "^2.2.1"
+            }
+        },
+        "fast-json-stable-stringify": {
+            "version": "2.1.0",
+            "resolved": 
"https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz";,
+            "integrity": 
"sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+            "dev": true
+        },
+        "fast-levenshtein": {
+            "version": "2.0.6",
+            "resolved": 
"https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz";,
+            "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+            "dev": true
+        },
+        "fastq": {
+            "version": "1.8.0",
+            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz";,
+            "integrity": 
"sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==",
+            "dev": true,
+            "requires": {
+                "reusify": "^1.0.4"
+            }
+        },
+        "file-entry-cache": {
+            "version": "5.0.1",
+            "resolved": 
"https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz";,
+            "integrity": 
"sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+            "dev": true,
+            "requires": {
+                "flat-cache": "^2.0.1"
+            }
+        },
+        "fill-range": {
+            "version": "7.0.1",
+            "resolved": 
"https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz";,
+            "integrity": 
"sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+            "dev": true,
+            "requires": {
+                "to-regex-range": "^5.0.1"
+            }
+        },
+        "find-up": {
+            "version": "2.1.0",
+            "resolved": 
"https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz";,
+            "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+            "dev": true,
+            "requires": {
+                "locate-path": "^2.0.0"
+            }
+        },
+        "flat-cache": {
+            "version": "2.0.1",
+            "resolved": 
"https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz";,
+            "integrity": 
"sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+            "dev": true,
+            "requires": {
+                "flatted": "^2.0.0",
+                "rimraf": "2.6.3",
+                "write": "1.0.3"
+            }
+        },
+        "flatted": {
+            "version": "2.0.2",
+            "resolved": 
"https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz";,
+            "integrity": 
"sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
+            "dev": true
+        },
+        "fs.realpath": {
+            "version": "1.0.0",
+            "resolved": 
"https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz";,
+            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+            "dev": true
+        },
+        "function-bind": {
+            "version": "1.1.1",
+            "resolved": 
"https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz";,
+            "integrity": 
"sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+            "dev": true
+        },
+        "functional-red-black-tree": {
+            "version": "1.0.1",
+            "resolved": 
"https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz";,
+            "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+            "dev": true
+        },
+        "glob": {
+            "version": "7.1.6",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz";,
+            "integrity": 
"sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+            "dev": true,
+            "requires": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.0.4",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+            }
+        },
+        "glob-parent": {
+            "version": "5.1.1",
+            "resolved": 
"https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz";,
+            "integrity": 
"sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+            "dev": true,
+            "requires": {
+                "is-glob": "^4.0.1"
+            }
+        },
+        "globals": {
+            "version": "12.4.0",
+            "resolved": 
"https://registry.npmjs.org/globals/-/globals-12.4.0.tgz";,
+            "integrity": 
"sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+            "dev": true,
+            "requires": {
+                "type-fest": "^0.8.1"
+            }
+        },
+        "globby": {
+            "version": "11.0.1",
+            "resolved": 
"https://registry.npmjs.org/globby/-/globby-11.0.1.tgz";,
+            "integrity": 
"sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==",
+            "dev": true,
+            "requires": {
+                "array-union": "^2.1.0",
+                "dir-glob": "^3.0.1",
+                "fast-glob": "^3.1.1",
+                "ignore": "^5.1.4",
+                "merge2": "^1.3.0",
+                "slash": "^3.0.0"
+            }
+        },
+        "graceful-fs": {
+            "version": "4.2.4",
+            "resolved": 
"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz";,
+            "integrity": 
"sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+            "dev": true
+        },
+        "has": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz";,
+            "integrity": 
"sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+            "dev": true,
+            "requires": {
+                "function-bind": "^1.1.1"
+            }
+        },
+        "has-flag": {
+            "version": "3.0.0",
+            "resolved": 
"https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz";,
+            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+            "dev": true
+        },
+        "has-symbols": {
+            "version": "1.0.1",
+            "resolved": 
"https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz";,
+            "integrity": 
"sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+            "dev": true
+        },
+        "hosted-git-info": {
+            "version": "2.8.8",
+            "resolved": 
"https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz";,
+            "integrity": 
"sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+            "dev": true
+        },
+        "ignore": {
+            "version": "5.1.8",
+            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz";,
+            "integrity": 
"sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+            "dev": true
+        },
+        "import-fresh": {
+            "version": "3.2.1",
+            "resolved": 
"https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz";,
+            "integrity": 
"sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+            "dev": true,
+            "requires": {
+                "parent-module": "^1.0.0",
+                "resolve-from": "^4.0.0"
+            }
+        },
+        "imurmurhash": {
+            "version": "0.1.4",
+            "resolved": 
"https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz";,
+            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+            "dev": true
+        },
+        "inflight": {
+            "version": "1.0.6",
+            "resolved": 
"https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz";,
+            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+            "dev": true,
+            "requires": {
+                "once": "^1.3.0",
+                "wrappy": "1"
+            }
+        },
+        "inherits": {
+            "version": "2.0.4",
+            "resolved": 
"https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz";,
+            "integrity": 
"sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+            "dev": true
+        },
+        "is-arrayish": {
+            "version": "0.2.1",
+            "resolved": 
"https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz";,
+            "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+            "dev": true
+        },
+        "is-callable": {
+            "version": "1.2.2",
+            "resolved": 
"https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz";,
+            "integrity": 
"sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==",
+            "dev": true
+        },
+        "is-core-module": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz";,
+            "integrity": 
"sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==",
+            "dev": true,
+            "requires": {
+                "has": "^1.0.3"
+            }
+        },
+        "is-date-object": {
+            "version": "1.0.2",
+            "resolved": 
"https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz";,
+            "integrity": 
"sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
+            "dev": true
+        },
+        "is-extglob": {
+            "version": "2.1.1",
+            "resolved": 
"https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz";,
+            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+            "dev": true
+        },
+        "is-fullwidth-code-point": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz";,
+            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+            "dev": true
+        },
+        "is-glob": {
+            "version": "4.0.1",
+            "resolved": 
"https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz";,
+            "integrity": 
"sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+            "dev": true,
+            "requires": {
+                "is-extglob": "^2.1.1"
+            }
+        },
+        "is-negative-zero": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz";,
+            "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=",
+            "dev": true
+        },
+        "is-number": {
+            "version": "7.0.0",
+            "resolved": 
"https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz";,
+            "integrity": 
"sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+            "dev": true
+        },
+        "is-regex": {
+            "version": "1.1.1",
+            "resolved": 
"https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz";,
+            "integrity": 
"sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
+            "dev": true,
+            "requires": {
+                "has-symbols": "^1.0.1"
+            }
+        },
+        "is-string": {
+            "version": "1.0.5",
+            "resolved": 
"https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz";,
+            "integrity": 
"sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
+            "dev": true
+        },
+        "is-symbol": {
+            "version": "1.0.3",
+            "resolved": 
"https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz";,
+            "integrity": 
"sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+            "dev": true,
+            "requires": {
+                "has-symbols": "^1.0.1"
+            }
+        },
+        "isarray": {
+            "version": "1.0.0",
+            "resolved": 
"https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz";,
+            "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+            "dev": true
+        },
+        "isexe": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz";,
+            "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+            "dev": true
+        },
+        "js-tokens": {
+            "version": "4.0.0",
+            "resolved": 
"https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz";,
+            "integrity": 
"sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+            "dev": true
+        },
+        "js-yaml": {
+            "version": "3.14.0",
+            "resolved": 
"https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz";,
+            "integrity": 
"sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+            "dev": true,
+            "requires": {
+                "argparse": "^1.0.7",
+                "esprima": "^4.0.0"
+            }
+        },
+        "jsdoctypeparser": {
+            "version": "9.0.0",
+            "resolved": 
"https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz";,
+            "integrity": 
"sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==",
+            "dev": true
+        },
+        "json-schema-traverse": {
+            "version": "0.4.1",
+            "resolved": 
"https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz";,
+            "integrity": 
"sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+            "dev": true
+        },
+        "json-stable-stringify-without-jsonify": {
+            "version": "1.0.1",
+            "resolved": 
"https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz";,
+            "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+            "dev": true
+        },
+        "json5": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz";,
+            "integrity": 
"sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+            "dev": true,
+            "requires": {
+                "minimist": "^1.2.0"
+            }
+        },
+        "levn": {
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz";,
+            "integrity": 
"sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+            "dev": true,
+            "requires": {
+                "prelude-ls": "^1.2.1",
+                "type-check": "~0.4.0"
+            }
+        },
+        "load-json-file": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz";,
+            "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+            "dev": true,
+            "requires": {
+                "graceful-fs": "^4.1.2",
+                "parse-json": "^2.2.0",
+                "pify": "^2.0.0",
+                "strip-bom": "^3.0.0"
+            }
+        },
+        "locate-path": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz";,
+            "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+            "dev": true,
+            "requires": {
+                "p-locate": "^2.0.0",
+                "path-exists": "^3.0.0"
+            }
+        },
+        "lodash": {
+            "version": "4.17.20",
+            "resolved": 
"https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz";,
+            "integrity": 
"sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+            "dev": true
+        },
+        "merge2": {
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz";,
+            "integrity": 
"sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+            "dev": true
+        },
+        "micromatch": {
+            "version": "4.0.2",
+            "resolved": 
"https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz";,
+            "integrity": 
"sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+            "dev": true,
+            "requires": {
+                "braces": "^3.0.1",
+                "picomatch": "^2.0.5"
+            }
+        },
+        "minimatch": {
+            "version": "3.0.4",
+            "resolved": 
"https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz";,
+            "integrity": 
"sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+            "dev": true,
+            "requires": {
+                "brace-expansion": "^1.1.7"
+            }
+        },
+        "minimist": {
+            "version": "1.2.5",
+            "resolved": 
"https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz";,
+            "integrity": 
"sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+            "dev": true
+        },
+        "mkdirp": {
+            "version": "0.5.5",
+            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz";,
+            "integrity": 
"sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+            "dev": true,
+            "requires": {
+                "minimist": "^1.2.5"
+            }
+        },
+        "ms": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz";,
+            "integrity": 
"sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+            "dev": true
+        },
+        "natural-compare": {
+            "version": "1.4.0",
+            "resolved": 
"https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz";,
+            "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+            "dev": true
+        },
+        "normalize-package-data": {
+            "version": "2.5.0",
+            "resolved": 
"https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz";,
+            "integrity": 
"sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+            "dev": true,
+            "requires": {
+                "hosted-git-info": "^2.1.4",
+                "resolve": "^1.10.0",
+                "semver": "2 || 3 || 4 || 5",
+                "validate-npm-package-license": "^3.0.1"
+            },
+            "dependencies": {
+                "semver": {
+                    "version": "5.7.1",
+                    "resolved": 
"https://registry.npmjs.org/semver/-/semver-5.7.1.tgz";,
+                    "integrity": 
"sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+                    "dev": true
+                }
+            }
+        },
+        "object-inspect": {
+            "version": "1.8.0",
+            "resolved": 
"https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz";,
+            "integrity": 
"sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
+            "dev": true
+        },
+        "object-keys": {
+            "version": "1.1.1",
+            "resolved": 
"https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz";,
+            "integrity": 
"sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+            "dev": true
+        },
+        "object.assign": {
+            "version": "4.1.1",
+            "resolved": 
"https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz";,
+            "integrity": 
"sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.3",
+                "es-abstract": "^1.18.0-next.0",
+                "has-symbols": "^1.0.1",
+                "object-keys": "^1.1.1"
+            },
+            "dependencies": {
+                "es-abstract": {
+                    "version": "1.18.0-next.1",
+                    "resolved": 
"https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz";,
+                    "integrity": 
"sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
+                    "dev": true,
+                    "requires": {
+                        "es-to-primitive": "^1.2.1",
+                        "function-bind": "^1.1.1",
+                        "has": "^1.0.3",
+                        "has-symbols": "^1.0.1",
+                        "is-callable": "^1.2.2",
+                        "is-negative-zero": "^2.0.0",
+                        "is-regex": "^1.1.1",
+                        "object-inspect": "^1.8.0",
+                        "object-keys": "^1.1.1",
+                        "object.assign": "^4.1.1",
+                        "string.prototype.trimend": "^1.0.1",
+                        "string.prototype.trimstart": "^1.0.1"
+                    }
+                }
+            }
+        },
+        "object.values": {
+            "version": "1.1.1",
+            "resolved": 
"https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz";,
+            "integrity": 
"sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.3",
+                "es-abstract": "^1.17.0-next.1",
+                "function-bind": "^1.1.1",
+                "has": "^1.0.3"
+            }
+        },
+        "once": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz";,
+            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+            "dev": true,
+            "requires": {
+                "wrappy": "1"
+            }
+        },
+        "optionator": {
+            "version": "0.9.1",
+            "resolved": 
"https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz";,
+            "integrity": 
"sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+            "dev": true,
+            "requires": {
+                "deep-is": "^0.1.3",
+                "fast-levenshtein": "^2.0.6",
+                "levn": "^0.4.1",
+                "prelude-ls": "^1.2.1",
+                "type-check": "^0.4.0",
+                "word-wrap": "^1.2.3"
+            }
+        },
+        "p-limit": {
+            "version": "1.3.0",
+            "resolved": 
"https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz";,
+            "integrity": 
"sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+            "dev": true,
+            "requires": {
+                "p-try": "^1.0.0"
+            }
+        },
+        "p-locate": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz";,
+            "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+            "dev": true,
+            "requires": {
+                "p-limit": "^1.1.0"
+            }
+        },
+        "p-try": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz";,
+            "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+            "dev": true
+        },
+        "parent-module": {
+            "version": "1.0.1",
+            "resolved": 
"https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz";,
+            "integrity": 
"sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+            "dev": true,
+            "requires": {
+                "callsites": "^3.0.0"
+            }
+        },
+        "parse-json": {
+            "version": "2.2.0",
+            "resolved": 
"https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz";,
+            "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+            "dev": true,
+            "requires": {
+                "error-ex": "^1.2.0"
+            }
+        },
+        "path-exists": {
+            "version": "3.0.0",
+            "resolved": 
"https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz";,
+            "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+            "dev": true
+        },
+        "path-is-absolute": {
+            "version": "1.0.1",
+            "resolved": 
"https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz";,
+            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+            "dev": true
+        },
+        "path-key": {
+            "version": "3.1.1",
+            "resolved": 
"https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz";,
+            "integrity": 
"sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+            "dev": true
+        },
+        "path-parse": {
+            "version": "1.0.6",
+            "resolved": 
"https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz";,
+            "integrity": 
"sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+            "dev": true
+        },
+        "path-type": {
+            "version": "4.0.0",
+            "resolved": 
"https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz";,
+            "integrity": 
"sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+            "dev": true
+        },
+        "picomatch": {
+            "version": "2.2.2",
+            "resolved": 
"https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz";,
+            "integrity": 
"sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+            "dev": true
+        },
+        "pify": {
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz";,
+            "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+            "dev": true
+        },
+        "pkg-dir": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz";,
+            "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+            "dev": true,
+            "requires": {
+                "find-up": "^2.1.0"
+            }
+        },
+        "prelude-ls": {
+            "version": "1.2.1",
+            "resolved": 
"https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz";,
+            "integrity": 
"sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+            "dev": true
+        },
+        "progress": {
+            "version": "2.0.3",
+            "resolved": 
"https://registry.npmjs.org/progress/-/progress-2.0.3.tgz";,
+            "integrity": 
"sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+            "dev": true
+        },
+        "punycode": {
+            "version": "2.1.1",
+            "resolved": 
"https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz";,
+            "integrity": 
"sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+            "dev": true
+        },
+        "read-pkg": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz";,
+            "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+            "dev": true,
+            "requires": {
+                "load-json-file": "^2.0.0",
+                "normalize-package-data": "^2.3.2",
+                "path-type": "^2.0.0"
+            },
+            "dependencies": {
+                "path-type": {
+                    "version": "2.0.0",
+                    "resolved": 
"https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz";,
+                    "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+                    "dev": true,
+                    "requires": {
+                        "pify": "^2.0.0"
+                    }
+                }
+            }
+        },
+        "read-pkg-up": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz";,
+            "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+            "dev": true,
+            "requires": {
+                "find-up": "^2.0.0",
+                "read-pkg": "^2.0.0"
+            }
+        },
+        "regexpp": {
+            "version": "3.1.0",
+            "resolved": 
"https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz";,
+            "integrity": 
"sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+            "dev": true
+        },
+        "regextras": {
+            "version": "0.7.1",
+            "resolved": 
"https://registry.npmjs.org/regextras/-/regextras-0.7.1.tgz";,
+            "integrity": 
"sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w==",
+            "dev": true
+        },
+        "resolve": {
+            "version": "1.18.1",
+            "resolved": 
"https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz";,
+            "integrity": 
"sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==",
+            "dev": true,
+            "requires": {
+                "is-core-module": "^2.0.0",
+                "path-parse": "^1.0.6"
+            }
+        },
+        "resolve-from": {
+            "version": "4.0.0",
+            "resolved": 
"https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz";,
+            "integrity": 
"sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+            "dev": true
+        },
+        "reusify": {
+            "version": "1.0.4",
+            "resolved": 
"https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz";,
+            "integrity": 
"sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+            "dev": true
+        },
+        "rimraf": {
+            "version": "2.6.3",
+            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz";,
+            "integrity": 
"sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+            "dev": true,
+            "requires": {
+                "glob": "^7.1.3"
+            }
+        },
+        "run-parallel": {
+            "version": "1.1.9",
+            "resolved": 
"https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz";,
+            "integrity": 
"sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==",
+            "dev": true
+        },
+        "semver": {
+            "version": "7.3.2",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz";,
+            "integrity": 
"sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+            "dev": true
+        },
+        "shebang-command": {
+            "version": "2.0.0",
+            "resolved": 
"https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz";,
+            "integrity": 
"sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+            "dev": true,
+            "requires": {
+                "shebang-regex": "^3.0.0"
+            }
+        },
+        "shebang-regex": {
+            "version": "3.0.0",
+            "resolved": 
"https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz";,
+            "integrity": 
"sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+            "dev": true
+        },
+        "slash": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz";,
+            "integrity": 
"sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+            "dev": true
+        },
+        "slice-ansi": {
+            "version": "2.1.0",
+            "resolved": 
"https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz";,
+            "integrity": 
"sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+            "dev": true,
+            "requires": {
+                "ansi-styles": "^3.2.0",
+                "astral-regex": "^1.0.0",
+                "is-fullwidth-code-point": "^2.0.0"
+            }
+        },
+        "spdx-correct": {
+            "version": "3.1.1",
+            "resolved": 
"https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz";,
+            "integrity": 
"sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+            "dev": true,
+            "requires": {
+                "spdx-expression-parse": "^3.0.0",
+                "spdx-license-ids": "^3.0.0"
+            }
+        },
+        "spdx-exceptions": {
+            "version": "2.3.0",
+            "resolved": 
"https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz";,
+            "integrity": 
"sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+            "dev": true
+        },
+        "spdx-expression-parse": {
+            "version": "3.0.1",
+            "resolved": 
"https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz";,
+            "integrity": 
"sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+            "dev": true,
+            "requires": {
+                "spdx-exceptions": "^2.1.0",
+                "spdx-license-ids": "^3.0.0"
+            }
+        },
+        "spdx-license-ids": {
+            "version": "3.0.6",
+            "resolved": 
"https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz";,
+            "integrity": 
"sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==",
+            "dev": true
+        },
+        "sprintf-js": {
+            "version": "1.0.3",
+            "resolved": 
"https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz";,
+            "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+            "dev": true
+        },
+        "string-width": {
+            "version": "3.1.0",
+            "resolved": 
"https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz";,
+            "integrity": 
"sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+            "dev": true,
+            "requires": {
+                "emoji-regex": "^7.0.1",
+                "is-fullwidth-code-point": "^2.0.0",
+                "strip-ansi": "^5.1.0"
+            },
+            "dependencies": {
+                "ansi-regex": {
+                    "version": "4.1.0",
+                    "resolved": 
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz";,
+                    "integrity": 
"sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+                    "dev": true
+                },
+                "strip-ansi": {
+                    "version": "5.2.0",
+                    "resolved": 
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz";,
+                    "integrity": 
"sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+                    "dev": true,
+                    "requires": {
+                        "ansi-regex": "^4.1.0"
+                    }
+                }
+            }
+        },
+        "string.prototype.trimend": {
+            "version": "1.0.2",
+            "resolved": 
"https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz";,
+            "integrity": 
"sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.3",
+                "es-abstract": "^1.18.0-next.1"
+            },
+            "dependencies": {
+                "es-abstract": {
+                    "version": "1.18.0-next.1",
+                    "resolved": 
"https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz";,
+                    "integrity": 
"sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
+                    "dev": true,
+                    "requires": {
+                        "es-to-primitive": "^1.2.1",
+                        "function-bind": "^1.1.1",
+                        "has": "^1.0.3",
+                        "has-symbols": "^1.0.1",
+                        "is-callable": "^1.2.2",
+                        "is-negative-zero": "^2.0.0",
+                        "is-regex": "^1.1.1",
+                        "object-inspect": "^1.8.0",
+                        "object-keys": "^1.1.1",
+                        "object.assign": "^4.1.1",
+                        "string.prototype.trimend": "^1.0.1",
+                        "string.prototype.trimstart": "^1.0.1"
+                    }
+                }
+            }
+        },
+        "string.prototype.trimstart": {
+            "version": "1.0.2",
+            "resolved": 
"https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz";,
+            "integrity": 
"sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.3",
+                "es-abstract": "^1.18.0-next.1"
+            },
+            "dependencies": {
+                "es-abstract": {
+                    "version": "1.18.0-next.1",
+                    "resolved": 
"https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz";,
+                    "integrity": 
"sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
+                    "dev": true,
+                    "requires": {
+                        "es-to-primitive": "^1.2.1",
+                        "function-bind": "^1.1.1",
+                        "has": "^1.0.3",
+                        "has-symbols": "^1.0.1",
+                        "is-callable": "^1.2.2",
+                        "is-negative-zero": "^2.0.0",
+                        "is-regex": "^1.1.1",
+                        "object-inspect": "^1.8.0",
+                        "object-keys": "^1.1.1",
+                        "object.assign": "^4.1.1",
+                        "string.prototype.trimend": "^1.0.1",
+                        "string.prototype.trimstart": "^1.0.1"
+                    }
+                }
+            }
+        },
+        "strip-ansi": {
+            "version": "6.0.0",
+            "resolved": 
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz";,
+            "integrity": 
"sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+            "dev": true,
+            "requires": {
+                "ansi-regex": "^5.0.0"
+            }
+        },
+        "strip-bom": {
+            "version": "3.0.0",
+            "resolved": 
"https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz";,
+            "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+            "dev": true
+        },
+        "strip-json-comments": {
+            "version": "3.1.1",
+            "resolved": 
"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz";,
+            "integrity": 
"sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+            "dev": true
+        },
+        "supports-color": {
+            "version": "5.5.0",
+            "resolved": 
"https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz";,
+            "integrity": 
"sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+            "dev": true,
+            "requires": {
+                "has-flag": "^3.0.0"
+            }
+        },
+        "table": {
+            "version": "5.4.6",
+            "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz";,
+            "integrity": 
"sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+            "dev": true,
+            "requires": {
+                "ajv": "^6.10.2",
+                "lodash": "^4.17.14",
+                "slice-ansi": "^2.1.0",
+                "string-width": "^3.0.0"
+            }
+        },
+        "text-table": {
+            "version": "0.2.0",
+            "resolved": 
"https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz";,
+            "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+            "dev": true
+        },
+        "to-regex-range": {
+            "version": "5.0.1",
+            "resolved": 
"https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz";,
+            "integrity": 
"sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+            "dev": true,
+            "requires": {
+                "is-number": "^7.0.0"
+            }
+        },
+        "tsconfig-paths": {
+            "version": "3.9.0",
+            "resolved": 
"https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz";,
+            "integrity": 
"sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==",
+            "dev": true,
+            "requires": {
+                "@types/json5": "^0.0.29",
+                "json5": "^1.0.1",
+                "minimist": "^1.2.0",
+                "strip-bom": "^3.0.0"
+            }
+        },
+        "tslib": {
+            "version": "1.14.1",
+            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz";,
+            "integrity": 
"sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+            "dev": true
+        },
+        "tslint": {
+            "version": "6.1.3",
+            "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz";,
+            "integrity": 
"sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==",
+            "dev": true,
+            "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "builtin-modules": "^1.1.1",
+                "chalk": "^2.3.0",
+                "commander": "^2.12.1",
+                "diff": "^4.0.1",
+                "glob": "^7.1.1",
+                "js-yaml": "^3.13.1",
+                "minimatch": "^3.0.4",
+                "mkdirp": "^0.5.3",
+                "resolve": "^1.3.2",
+                "semver": "^5.3.0",
+                "tslib": "^1.13.0",
+                "tsutils": "^2.29.0"
+            },
+            "dependencies": {
+                "chalk": {
+                    "version": "2.4.2",
+                    "resolved": 
"https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz";,
+                    "integrity": 
"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+                    "dev": true,
+                    "requires": {
+                        "ansi-styles": "^3.2.1",
+                        "escape-string-regexp": "^1.0.5",
+                        "supports-color": "^5.3.0"
+                    }
+                },
+                "semver": {
+                    "version": "5.7.1",
+                    "resolved": 
"https://registry.npmjs.org/semver/-/semver-5.7.1.tgz";,
+                    "integrity": 
"sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+                    "dev": true
+                },
+                "tsutils": {
+                    "version": "2.29.0",
+                    "resolved": 
"https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz";,
+                    "integrity": 
"sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+                    "dev": true,
+                    "requires": {
+                        "tslib": "^1.8.1"
+                    }
+                }
+            }
+        },
+        "tsutils": {
+            "version": "3.17.1",
+            "resolved": 
"https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz";,
+            "integrity": 
"sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
+            "dev": true,
+            "requires": {
+                "tslib": "^1.8.1"
+            }
+        },
+        "type-check": {
+            "version": "0.4.0",
+            "resolved": 
"https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz";,
+            "integrity": 
"sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+            "dev": true,
+            "requires": {
+                "prelude-ls": "^1.2.1"
+            }
+        },
+        "type-fest": {
+            "version": "0.8.1",
+            "resolved": 
"https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz";,
+            "integrity": 
"sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+            "dev": true
+        },
+        "typescript": {
+            "version": "4.0.3",
+            "resolved": 
"https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz";,
+            "integrity": 
"sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==",
+            "dev": true
+        },
+        "uri-js": {
+            "version": "4.4.0",
+            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz";,
+            "integrity": 
"sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
+            "dev": true,
+            "requires": {
+                "punycode": "^2.1.0"
+            }
+        },
+        "v8-compile-cache": {
+            "version": "2.1.1",
+            "resolved": 
"https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz";,
+            "integrity": 
"sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
+            "dev": true
+        },
+        "validate-npm-package-license": {
+            "version": "3.0.4",
+            "resolved": 
"https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz";,
+            "integrity": 
"sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+            "dev": true,
+            "requires": {
+                "spdx-correct": "^3.0.0",
+                "spdx-expression-parse": "^3.0.0"
+            }
+        },
+        "which": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz";,
+            "integrity": 
"sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+            "dev": true,
+            "requires": {
+                "isexe": "^2.0.0"
+            }
+        },
+        "word-wrap": {
+            "version": "1.2.3",
+            "resolved": 
"https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz";,
+            "integrity": 
"sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+            "dev": true
+        },
+        "wrappy": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz";,
+            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+            "dev": true
+        },
+        "write": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz";,
+            "integrity": 
"sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+            "dev": true,
+            "requires": {
+                "mkdirp": "^0.5.1"
+            }
+        }
+    }
+}
diff --git a/.github/actions/to-integration-tests/package.json 
b/.github/actions/to-integration-tests/package.json
new file mode 100644
index 0000000..bc27ff1
--- /dev/null
+++ b/.github/actions/to-integration-tests/package.json
@@ -0,0 +1,24 @@
+{
+       "author": "Apache Traffic Control",
+       "description": "Runs Traffic Ops Go client/API integration tests",
+       "license": "Apache-2.0",
+       "main": "dist/to-integration-tests.js",
+       "name": "to-integration-tests",
+       "version": "0.0.0",
+       "scripts": {
+               "build": "tsc",
+               "lint": "eslint to-integration-tests.ts",
+               "all": "npm run lint && npm run build"
+       },
+       "devDependencies": {
+               "@types/node": "^14.14.0",
+               "@typescript-eslint/eslint-plugin": "^4.5.0",
+               "@typescript-eslint/eslint-plugin-tslint": "^4.6.0",
+               "@typescript-eslint/parser": "^4.5.0",
+               "eslint": "^7.11.0",
+               "eslint-plugin-import": "^2.22.1",
+               "eslint-plugin-jsdoc": "^30.7.3",
+               "tslint": "^6.1.3",
+               "typescript": "^4.0.3"
+       }
+}
diff --git a/.github/actions/to-integration-tests/riak.json 
b/.github/actions/to-integration-tests/riak.json
new file mode 100644
index 0000000..b13cd05
--- /dev/null
+++ b/.github/actions/to-integration-tests/riak.json
@@ -0,0 +1,8 @@
+{
+       "user": "${TV_RIAK_USER}",
+       "password": "${TV_RIAK_PASSWORD}",
+       "MaxTLSVersion": "1.1",
+       "tlsConfig": {
+               "insecureSkipVerify": true
+       }
+}
diff --git a/.github/actions/to-integration-tests/to-integration-tests.ts 
b/.github/actions/to-integration-tests/to-integration-tests.ts
new file mode 100644
index 0000000..d0076e0
--- /dev/null
+++ b/.github/actions/to-integration-tests/to-integration-tests.ts
@@ -0,0 +1,31 @@
+/*
+* 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.
+*/
+
+"use strict";
+import child_process, { SpawnSyncOptions, SpawnSyncReturns } from 
"child_process";
+import path from "path";
+
+const spawnOptions: SpawnSyncOptions = {stdio: "inherit"};
+
+function runProcess(...commandArguments: string[]): void {
+       console.info(...commandArguments);
+       const {status}: SpawnSyncReturns<Buffer> = 
child_process.spawnSync(commandArguments[0], commandArguments.slice(1), 
spawnOptions);
+       if (status === 0) {
+               return;
+       }
+       console.error("Child process \"", ...commandArguments, "\" exited with 
status code", status, "!");
+       process.exit(status ?? 1);
+}
+
+runProcess(path.join(__dirname, "../entrypoint.sh"));
diff --git a/.github/actions/to-integration-tests/traffic-ops-test.json 
b/.github/actions/to-integration-tests/traffic-ops-test.json
index 78c96ea..1c7298e 100644
--- a/.github/actions/to-integration-tests/traffic-ops-test.json
+++ b/.github/actions/to-integration-tests/traffic-ops-test.json
@@ -9,10 +9,11 @@
                },
                "session": {
                        "timeoutInSecs": 60
-               }
+               },
+               "includeSystemTests": true
        },
        "trafficOps": {
-               "URL": "https://localhost:6443";,
+               "URL": "https://127.0.0.1:6443";,
                "password": "twelve",
                "users": {
                        "disallowed": "disallowed",
@@ -27,7 +28,7 @@
        "trafficOpsDB": {
                "dbname": "traffic_ops",
                "description": "Test database to_test",
-               "hostname": "postgres",
+               "hostname": "172.17.0.1",
                "password": "twelve",
                "port": "5432",
                "type": "Pg",
diff --git a/.github/actions/to-integration-tests/tsconfig.json 
b/.github/actions/to-integration-tests/tsconfig.json
new file mode 100644
index 0000000..78c8c92
--- /dev/null
+++ b/.github/actions/to-integration-tests/tsconfig.json
@@ -0,0 +1,14 @@
+{
+       "compilerOptions": {
+               "target": "es6",                /* Specify ECMAScript target 
version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 
'ES2019' or 'ESNEXT'. */
+               "module": "commonjs",           /* Specify module code 
generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 
*/
+               "outDir": "./dist",             /* Redirect output structure to 
the directory. */
+               "rootDir": ".",                 /* Specify the root directory 
of input files. Use to control the output directory structure with --outDir. */
+               "strict": true,                 /* Enable all strict 
type-checking options. */
+               "noImplicitAny": true,          /* Raise error on expressions 
and declarations with an implied 'any' type. */
+               "esModuleInterop": true         /* Enables emit 
interoperability between CommonJS and ES Modules via creation of namespace 
objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+       },
+       "exclude": [
+               "node_modules"
+       ]
+}
diff --git a/.github/workflows/traffic ops.yml b/.github/workflows/traffic 
ops.yml
index c568431..5aa60bd 100644
--- a/.github/workflows/traffic ops.yml 
+++ b/.github/workflows/traffic ops.yml 
@@ -49,6 +49,20 @@ jobs:
         - 5432:5432
         options: --health-cmd pg_isready --health-interval 10s 
--health-timeout 5s --health-retries 5
 
+      smtp:
+        image: maildev/maildev:2.0.0-beta3
+        ports:
+          - 25:25
+        options: >-
+          --entrypoint=bin/maildev
+          --user=root
+          --health-cmd="sh -c \"[[ \$(wget -qO- http://smtp/healthz) == true 
]]\""
+          --
+          maildev/maildev:2.0.0-beta3
+          --smtp=25
+          --hide-extensions=STARTTLS
+          --web=80
+
     steps:
     - name: Checkout
       uses: actions/checkout@master
@@ -64,8 +78,10 @@ jobs:
       uses: ./.github/actions/to-integration-tests
       with:
         version: 2
+        smtp_address: 172.17.0.1
     - name: Run API v3 tests
       if: ${{ steps.todb.outcome == 'success' && always() }}
       uses: ./.github/actions/to-integration-tests
       with:
         version: 3
+        smtp_address: 172.17.0.1
diff --git a/.gitignore b/.gitignore
index 033cdd8..d05407f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@ traffic_router/*.log
 *.pyc
 bin/docker-compose
 /.m2
+/.github/actions/**/node_modules/
 # local storage for cdn-in-a-box Carton packages
 local.tar.gz
 # Editor/IDE configuration files
diff --git a/traffic_ops/testing/api/v3/serverservercapability_test.go 
b/traffic_ops/testing/api/v3/serverservercapability_test.go
index c5112c0..06af56d 100644
--- a/traffic_ops/testing/api/v3/serverservercapability_test.go
+++ b/traffic_ops/testing/api/v3/serverservercapability_test.go
@@ -133,10 +133,10 @@ func CreateTestServerServerCapabilities(t *testing.T) {
 
        // Attempt to assign a server capability to a non MID/EDGE server
        // TODO: DON'T hard-code server hostnames!
-       params.Set("hostName", "riak")
+       params.Set("hostName", "trafficvault")
        resp, _, err := TOSession.GetServersWithHdr(&params, nil)
        if err != nil {
-               t.Fatalf("cannot GET Server by hostname 'riak': %v - %v", err, 
resp.Alerts)
+               t.Fatalf("cannot GET Server by hostname 'trafficvault': %v - 
%v", err, resp.Alerts)
        }
        servers := resp.Response
        if len(servers) < 1 {
diff --git a/traffic_ops/testing/api/v3/tc-fixtures.json 
b/traffic_ops/testing/api/v3/tc-fixtures.json
index 19e31c8..703e250 100644
--- a/traffic_ops/testing/api/v3/tc-fixtures.json
+++ b/traffic_ops/testing/api/v3/tc-fixtures.json
@@ -2618,9 +2618,9 @@
         {
             "cachegroup": "cachegroup1",
             "cdnName": "cdn1",
-            "domainName": "local",
+            "domainName": "infra.ciab.test",
             "guid": null,
-            "hostName": "riak",
+            "hostName": "trafficvault",
             "httpsPort": 8088,
             "iloIpAddress": "",
             "iloIpGateway": "",
@@ -2658,7 +2658,7 @@
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
-            "status": "REPORTED",
+            "status": "ONLINE",
             "tcpPort": 8088,
             "type": "RIAK",
             "updPending": false,

Reply via email to