Repository: kubernetes-client/javascript
Pull request #1033 (2023-03-31 08:07:53)

fix: remove final refrences to request + fix tests
I removed the request library (had to install form-data instead of it)
I added the node-fetch types
fixed log, watch, catch and metrics
Fixed all tests



Patch:
diff --git a/FETCH_MIGRATION.md b/FETCH_MIGRATION.md
index c34e9d15..43d7a9f6 100644
--- a/FETCH_MIGRATION.md
+++ b/FETCH_MIGRATION.md
@@ -51,12 +51,12 @@ Code will be on the `master` branch.
 -   [x] Match src/gen/api.ts to new generated layout (it changes slightly)
 -   [ ] Fix errors in /src folder (due to new api)
     -   [x] migrate src/auth.ts, the dependent implementations (ex: azure_auth, gcp_auth etc) and tests to fetch api from request
-    -   [ ] migrate src/log.ts and its tests to fetch api from request
-        -   major remaining work is fixing up async signatures and return piping
-    -   [ ] migrate src/watch.ts and its tests to fetch api from request
-        -   remove decprecated requestImpl and RequestInterface
-        -   implement queryParams parameter in watch method by injecting them into the fetch call
-        -   update tests in src/watch_test.ts
+    -   [x] migrate src/log.ts and its tests to fetch api from request
+        -  [x] major remaining work is fixing up async signatures and return piping
+    -   [x] migrate src/watch.ts and its tests to fetch api from request
+        -  [x] remove decprecated requestImpl and RequestInterface
+        -  [x] implement queryParams parameter in watch method by injecting them into the fetch call
+        -  [x] update tests in src/watch_test.ts
 -   [ ] Fix errors in test (due to new api)
 -   [ ] Test all features
 -   [ ] Fix examples and validate their param signatures (due to new api)
diff --git a/package-lock.json b/package-lock.json
index f1e3da42..83fc603b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,7 @@
             "dependencies": {
                 "@types/js-yaml": "^4.0.1",
                 "@types/node": "^10.12.0",
-                "@types/request": "^2.47.1",
+                "@types/node-fetch": "^2.6.3",
                 "@types/stream-buffers": "^3.0.3",
                 "@types/tar": "^6.1.1",
                 "@types/underscore": "^1.8.9",
@@ -19,12 +19,12 @@
                 "abort-controller": "^3.0.0",
                 "byline": "^5.0.0",
                 "execa": "5.0.0",
+                "form-data": "^4.0.0",
                 "isomorphic-ws": "^4.0.1",
                 "js-yaml": "^4.1.0",
                 "jsonpath-plus": "^0.19.0",
-                "node-fetch": "^2.6.0",
+                "node-fetch": "^2.6.9",
                 "openid-client": "^4.1.1",
-                "request": "^2.88.0",
                 "rfc4648": "^1.3.0",
                 "shelljs": "^0.8.5",
                 "stream-buffers": "^3.0.2",
@@ -91,6 +91,10 @@
             },
             "engines": {
                 "node": ">=6.9.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/babel"
             }
         },
         "node_modules/@babel/core/node_modules/@babel/code-frame": {
@@ -471,11 +475,6 @@
                 "@types/responselike": "*"
             }
         },
-        "node_modules/@types/caseless": {
-            "version": "0.12.1",
-            "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz",
-            "integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A=="
-        },
         "node_modules/@types/chai": {
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz",
@@ -496,14 +495,6 @@
             "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
             "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA=="
         },
-        "node_modules/@types/form-data": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
-            "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
         "node_modules/@types/http-cache-semantics": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz",
@@ -550,15 +541,26 @@
             "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz",
             "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ=="
         },
-        "node_modules/@types/request": {
-            "version": "2.47.1",
-            "resolved": "https://registry.npmjs.org/@types/request/-/request-2.47.1.tgz",
-            "integrity": "sha512-TV3XLvDjQbIeVxJ1Z3oCTDk/KuYwwcNKVwz2YaT0F5u86Prgc4syDAp6P96rkTQQ4bIdh+VswQIC9zS6NjY7/g==",
+        "node_modules/@types/node-fetch": {
+            "version": "2.6.3",
+            "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz",
+            "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==",
             "dependencies": {
-                "@types/caseless": "*",
-                "@types/form-data": "*",
                 "@types/node": "*",
-                "@types/tough-cookie": "*"
+                "form-data": "^3.0.0"
+            }
+        },
+        "node_modules/@types/node-fetch/node_modules/form-data": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+            "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+            "dependencies": {
+                "asynckit": "^0.4.0",
+                "combined-stream": "^1.0.8",
+                "mime-types": "^2.1.12"
+            },
+            "engines": {
+                "node": ">= 6"
             }
         },
         "node_modules/@types/responselike": {
@@ -586,11 +588,6 @@
                 "@types/node": "*"
             }
         },
-        "node_modules/@types/tough-cookie": {
-            "version": "2.3.3",
-            "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.3.tgz",
-            "integrity": "sha512-MDQLxNFRLasqS4UlkWMSACMKeSm1x4Q3TxzUC7KQUsh6RK1ZrQ0VEyE3yzXcBu+K8ejVj4wuX32eUG02yNp+YQ=="
-        },
         "node_modules/@types/underscore": {
             "version": "1.8.9",
             "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.8.9.tgz",
@@ -628,21 +625,6 @@
                 "node": ">=8"
             }
         },
-        "node_modules/ajv": {
-            "version": "6.12.6",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.1",
-                "fast-json-stable-stringify": "^2.0.0",
-                "json-schema-traverse": "^0.4.1",
-                "uri-js": "^4.2.2"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/epoberezkin"
-            }
-        },
         "node_modules/ansi-colors": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
@@ -725,22 +707,6 @@
                 "sprintf-js": "~1.0.2"
             }
         },
-        "node_modules/asn1": {
-            "version": "0.2.4",
-            "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
-            "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
-            "dependencies": {
-                "safer-buffer": "~2.1.0"
-            }
-        },
-        "node_modules/assert-plus": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-            "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
         "node_modules/assertion-error": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
@@ -753,20 +719,7 @@
         "node_modules/asynckit": {
             "version": "0.4.0",
             "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-            "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
-        },
-        "node_modules/aws-sign2": {
-            "version": "0.7.0",
-            "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-            "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/aws4": {
-            "version": "1.8.0",
-            "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
-            "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
+            "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
         },
         "node_modules/balanced-match": {
             "version": "1.0.0",
@@ -781,14 +734,6 @@
                 "node": ">=6.0.0"
             }
         },
-        "node_modules/bcrypt-pbkdf": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-            "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
-            "dependencies": {
-                "tweetnacl": "^0.14.3"
-            }
-        },
         "node_modules/binary-extensions": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@@ -911,11 +856,6 @@
                 "node": ">=6"
             }
         },
-        "node_modules/caseless": {
-            "version": "0.12.0",
-            "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
-        },
         "node_modules/chai": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
@@ -940,6 +880,9 @@
             "dev": true,
             "dependencies": {
                 "check-error": "^1.0.2"
+            },
+            "peerDependencies": {
+                "chai": ">= 2.1.2 < 5"
             }
         },
         "node_modules/chalk": {
@@ -1058,9 +1001,9 @@
             "dev": true
         },
         "node_modules/combined-stream": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
-            "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+            "version": "1.0.8",
+            "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+            "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
             "dependencies": {
                 "delayed-stream": "~1.0.0"
             },
@@ -1094,11 +1037,6 @@
                 "safe-buffer": "~5.1.1"
             }
         },
-        "node_modules/core-util-is": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-            "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
-        },
         "node_modules/cross-spawn": {
             "version": "7.0.3",
             "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -1126,17 +1064,6 @@
                 "node": ">= 8"
             }
         },
-        "node_modules/dashdash": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-            "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
-            "dependencies": {
-                "assert-plus": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
         "node_modules/debug": {
             "version": "4.3.4",
             "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -1178,6 +1105,9 @@
             },
             "engines": {
                 "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/decompress-response/node_modules/mimic-response": {
@@ -1186,6 +1116,9 @@
             "integrity": "sha1-LR1Zr5wbEpgVrMwsRqAipc4fo8k=",
             "engines": {
                 "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/deep-eql": {
@@ -1223,7 +1156,7 @@
         "node_modules/delayed-stream": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-            "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+            "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
             "engines": {
                 "node": ">=0.4.0"
             }
@@ -1237,15 +1170,6 @@
                 "node": ">=0.3.1"
             }
         },
-        "node_modules/ecc-jsbn": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-            "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
-            "dependencies": {
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.1.0"
-            }
-        },
         "node_modules/emoji-regex": {
             "version": "8.0.0",
             "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -1336,29 +1260,6 @@
                 "url": "https://github.com/sindresorhus/execa?sponsor=1"
             }
         },
-        "node_modules/extend": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-            "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
-        },
-        "node_modules/extsprintf": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-            "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
-            "engines": [
-                "node >=0.6.0"
-            ]
-        },
-        "node_modules/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=="
-        },
-        "node_modules/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=="
-        },
         "node_modules/fill-range": {
             "version": "7.0.1",
             "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -1383,6 +1284,9 @@
             },
             "engines": {
                 "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
             }
         },
         "node_modules/find-up": {
@@ -1423,32 +1327,38 @@
                 "node": ">=8.0.0"
             }
         },
-        "node_modules/forever-agent": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-            "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
-            "engines": {
-                "node": "*"
-            }
-        },
         "node_modules/form-data": {
-            "version": "2.3.3",
-            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
-            "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+            "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
             "dependencies": {
                 "asynckit": "^0.4.0",
-                "combined-stream": "^1.0.6",
+                "combined-stream": "^1.0.8",
                 "mime-types": "^2.1.12"
             },
             "engines": {
-                "node": ">= 0.12"
+                "node": ">= 6"
             }
         },
         "node_modules/fromentries": {
             "version": "1.3.2",
             "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
             "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
-            "dev": true
+            "dev": true,
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ]
         },
         "node_modules/fs-minipass": {
             "version": "2.1.0",
@@ -1527,14 +1437,6 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
-        "node_modules/getpass": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-            "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
-            "dependencies": {
-                "assert-plus": "^1.0.0"
-            }
-        },
         "node_modules/glob": {
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
@@ -1605,27 +1507,6 @@
             "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
             "dev": true
         },
-        "node_modules/har-schema": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-            "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/har-validator": {
-            "version": "5.1.5",
-            "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
-            "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
-            "deprecated": "this library is no longer supported",
-            "dependencies": {
-                "ajv": "^6.12.3",
-                "har-schema": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
         "node_modules/has-flag": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -1646,6 +1527,9 @@
             },
             "engines": {
                 "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/hasha/node_modules/type-fest": {
@@ -1677,20 +1561,6 @@
             "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
             "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
         },
-        "node_modules/http-signature": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-            "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
-            "dependencies": {
-                "assert-plus": "^1.0.0",
-                "jsprim": "^1.2.2",
-                "sshpk": "^1.7.0"
-            },
-            "engines": {
-                "node": ">=0.8",
-                "npm": ">=1.3.7"
-            }
-        },
         "node_modules/http2-wrapper": {
             "version": "1.0.0-beta.5.2",
             "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz",
@@ -1833,7 +1703,8 @@
         "node_modules/is-typedarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+            "dev": true
         },
         "node_modules/is-unicode-supported": {
             "version": "0.1.0",
@@ -1864,12 +1735,10 @@
         "node_modules/isomorphic-ws": {
             "version": "4.0.1",
             "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
-            "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w=="
-        },
-        "node_modules/isstream": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-            "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+            "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
+            "peerDependencies": {
+                "ws": "*"
+            }
         },
         "node_modules/istanbul-lib-coverage": {
             "version": "3.0.0",
@@ -1938,6 +1807,7 @@
             "version": "3.4.0",
             "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
             "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+            "deprecated": "Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.",
             "dev": true,
             "bin": {
                 "uuid": "bin/uuid"
@@ -2069,11 +1939,6 @@
             "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
             "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
         },
-        "node_modules/jsbn": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-            "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
-        },
         "node_modules/jsesc": {
             "version": "2.5.2",
             "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@@ -2091,20 +1956,11 @@
             "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
             "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
         },
-        "node_modules/json-schema": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
-            "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
-        },
-        "node_modules/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=="
-        },
         "node_modules/json-stringify-safe": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+            "dev": true
         },
         "node_modules/json5": {
             "version": "2.2.3",
@@ -2132,20 +1988,6 @@
                 "node": ">=6.0"
             }
         },
-        "node_modules/jsprim": {
-            "version": "1.4.2",
-            "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
-            "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
-            "dependencies": {
-                "assert-plus": "1.0.0",
-                "extsprintf": "1.3.0",
-                "json-schema": "0.4.0",
-                "verror": "1.10.0"
-            },
-            "engines": {
-                "node": ">=0.6.0"
-            }
-        },
         "node_modules/keyv": {
             "version": "4.5.2",
             "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
@@ -2285,6 +2127,9 @@
             },
             "engines": {
                 "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/make-dir/node_modules/semver": {
@@ -2320,19 +2165,19 @@
             "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
         },
         "node_modules/mime-db": {
-            "version": "1.36.0",
-            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
-            "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==",
+            "version": "1.52.0",
+            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+            "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
             "engines": {
                 "node": ">= 0.6"
             }
         },
         "node_modules/mime-types": {
-            "version": "2.1.20",
-            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
-            "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
+            "version": "2.1.35",
+            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+            "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
             "dependencies": {
-                "mime-db": "~1.36.0"
+                "mime-db": "1.52.0"
             },
             "engines": {
                 "node": ">= 0.6"
@@ -2780,14 +2625,6 @@
                 "node": ">=8"
             }
         },
-        "node_modules/oauth-sign": {
-            "version": "0.9.0",
-            "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
-            "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
-            "engines": {
-                "node": "*"
-            }
-        },
         "node_modules/object-hash": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz",
@@ -2842,6 +2679,9 @@
             },
             "engines": {
                 "node": "^10.19.0 || >=12.0.0 < 13 || >=13.7.0 < 14 || >= 14.2.0"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/panva"
             }
         },
         "node_modules/openid-client/node_modules/lru-cache": {
@@ -2875,6 +2715,9 @@
             },
             "engines": {
                 "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/p-cancelable": {
@@ -2949,6 +2792,9 @@
             },
             "engines": {
                 "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/p-try": {
@@ -3014,11 +2860,6 @@
                 "node": "*"
             }
         },
-        "node_modules/performance-now": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-            "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
-        },
         "node_modules/picomatch": {
             "version": "2.3.1",
             "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
@@ -3115,11 +2956,6 @@
                 "node": ">= 8"
             }
         },
-        "node_modules/psl": {
-            "version": "1.1.29",
-            "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
-            "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
-        },
         "node_modules/pump": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@@ -3129,19 +2965,6 @@
                 "once": "^1.3.1"
             }
         },
-        "node_modules/punycode": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-            "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
-        },
-        "node_modules/qs": {
-            "version": "6.5.3",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
-            "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
-            "engines": {
-                "node": ">=0.6"
-            }
-        },
         "node_modules/querystringify": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
@@ -3153,6 +2976,9 @@
             "integrity": "sha1-NmST5rPkKjpoheLpnRj4D7eoyTI=",
             "engines": {
                 "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/randombytes": {
@@ -3199,36 +3025,6 @@
                 "node": ">=4"
             }
         },
-        "node_modules/request": {
-            "version": "2.88.0",
-            "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
-            "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
-            "dependencies": {
-                "aws-sign2": "~0.7.0",
-                "aws4": "^1.8.0",
-                "caseless": "~0.12.0",
-                "combined-stream": "~1.0.6",
-                "extend": "~3.0.2",
-                "forever-agent": "~0.6.1",
-                "form-data": "~2.3.2",
-                "har-validator": "~5.1.0",
-                "http-signature": "~1.2.0",
-                "is-typedarray": "~1.0.0",
-                "isstream": "~0.1.2",
-                "json-stringify-safe": "~5.0.1",
-                "mime-types": "~2.1.19",
-                "oauth-sign": "~0.9.0",
-                "performance-now": "^2.1.0",
-                "qs": "~6.5.2",
-                "safe-buffer": "^5.1.2",
-                "tough-cookie": "~2.4.3",
-                "tunnel-agent": "^0.6.0",
-                "uuid": "^3.3.2"
-            },
-            "engines": {
-                "node": ">= 4"
-            }
-        },
         "node_modules/require-directory": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -3287,17 +3083,16 @@
             },
             "bin": {
                 "rimraf": "bin.js"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
             }
         },
         "node_modules/safe-buffer": {
             "version": "5.1.2",
             "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-            "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
-        },
-        "node_modules/safer-buffer": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-            "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+            "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+            "dev": true
         },
         "node_modules/semver": {
             "version": "5.5.1",
@@ -3441,25 +3236,6 @@
             "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
             "dev": true
         },
-        "node_modules/sshpk": {
-            "version": "1.15.1",
-            "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz",
-            "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==",
-            "dependencies": {
-                "asn1": "~0.2.3",
-                "assert-plus": "^1.0.0",
-                "bcrypt-pbkdf": "^1.0.0",
-                "dashdash": "^1.12.0",
-                "ecc-jsbn": "~0.1.1",
-                "getpass": "^0.1.1",
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.0.2",
-                "tweetnacl": "~0.14.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
         "node_modules/stream-buffers": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz",
@@ -3633,18 +3409,6 @@
                 "node": ">=8.0"
             }
         },
-        "node_modules/tough-cookie": {
-            "version": "2.4.3",
-            "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
-            "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
-            "dependencies": {
-                "psl": "^1.1.24",
-                "punycode": "^1.4.1"
-            },
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
         "node_modules/tr46": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -3676,6 +3440,9 @@
             },
             "engines": {
                 "node": ">=4.2.0"
+            },
+            "peerDependencies": {
+                "typescript": ">=2.0"
             }
         },
         "node_modules/ts-node/node_modules/diff": {
@@ -3717,6 +3484,9 @@
             },
             "engines": {
                 "node": ">=4.8.0"
+            },
+            "peerDependencies": {
+                "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev"
             }
         },
         "node_modules/tslint/node_modules/js-yaml": {
@@ -3739,24 +3509,11 @@
             "dev": true,
             "dependencies": {
                 "tslib": "^1.8.1"
-            }
-        },
-        "node_modules/tunnel-agent": {
-            "version": "0.6.0",
-            "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
-            "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
-            "dependencies": {
-                "safe-buffer": "^5.0.1"
             },
-            "engines": {
-                "node": "*"
+            "peerDependencies": {
+                "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev"
             }
         },
-        "node_modules/tweetnacl": {
-            "version": "0.14.5",
-            "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-            "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
-        },
         "node_modules/type-detect": {
             "version": "4.0.8",
             "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
@@ -3838,22 +3595,6 @@
             "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
             "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw=="
         },
-        "node_modules/uri-js": {
-            "version": "4.4.1",
-            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-            "dependencies": {
-                "punycode": "^2.1.0"
-            }
-        },
-        "node_modules/uri-js/node_modules/punycode": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
-            "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
         "node_modules/url-parse": {
             "version": "1.5.10",
             "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
@@ -3863,27 +3604,6 @@
                 "requires-port": "^1.0.0"
             }
         },
-        "node_modules/uuid": {
-            "version": "3.3.2",
-            "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
-            "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
-            "bin": {
-                "uuid": "bin/uuid"
-            }
-        },
-        "node_modules/verror": {
-            "version": "1.10.0",
-            "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
-            "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
-            "engines": [
-                "node >=0.6.0"
-            ],
-            "dependencies": {
-                "assert-plus": "^1.0.0",
-                "core-util-is": "1.0.2",
-                "extsprintf": "^1.2.0"
-            }
-        },
         "node_modules/vscode-oniguruma": {
             "version": "1.7.0",
             "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
@@ -3946,6 +3666,9 @@
             },
             "engines": {
                 "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
             }
         },
         "node_modules/wrap-ansi/node_modules/color-convert": {
@@ -4516,11 +4239,6 @@
                 "@types/responselike": "*"
             }
         },
-        "@types/caseless": {
-            "version": "0.12.1",
-            "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz",
-            "integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A=="
-        },
         "@types/chai": {
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz",
@@ -4541,14 +4259,6 @@
             "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
             "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA=="
         },
-        "@types/form-data": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
-            "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
-            "requires": {
-                "@types/node": "*"
-            }
-        },
         "@types/http-cache-semantics": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz",
@@ -4595,15 +4305,25 @@
             "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz",
             "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ=="
         },
-        "@types/request": {
-            "version": "2.47.1",
-            "resolved": "https://registry.npmjs.org/@types/request/-/request-2.47.1.tgz",
-            "integrity": "sha512-TV3XLvDjQbIeVxJ1Z3oCTDk/KuYwwcNKVwz2YaT0F5u86Prgc4syDAp6P96rkTQQ4bIdh+VswQIC9zS6NjY7/g==",
+        "@types/node-fetch": {
+            "version": "2.6.3",
+            "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz",
+            "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==",
             "requires": {
-                "@types/caseless": "*",
-                "@types/form-data": "*",
                 "@types/node": "*",
-                "@types/tough-cookie": "*"
+                "form-data": "^3.0.0"
+            },
+            "dependencies": {
+                "form-data": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+                    "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+                    "requires": {
+                        "asynckit": "^0.4.0",
+                        "combined-stream": "^1.0.8",
+                        "mime-types": "^2.1.12"
+                    }
+                }
             }
         },
         "@types/responselike": {
@@ -4631,11 +4351,6 @@
                 "@types/node": "*"
             }
         },
-        "@types/tough-cookie": {
-            "version": "2.3.3",
-            "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.3.tgz",
-            "integrity": "sha512-MDQLxNFRLasqS4UlkWMSACMKeSm1x4Q3TxzUC7KQUsh6RK1ZrQ0VEyE3yzXcBu+K8ejVj4wuX32eUG02yNp+YQ=="
-        },
         "@types/underscore": {
             "version": "1.8.9",
             "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.8.9.tgz",
@@ -4667,17 +4382,6 @@
                 "indent-string": "^4.0.0"
             }
         },
-        "ajv": {
-            "version": "6.12.6",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-            "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",
@@ -4745,19 +4449,6 @@
                 "sprintf-js": "~1.0.2"
             }
         },
-        "asn1": {
-            "version": "0.2.4",
-            "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
-            "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
-            "requires": {
-                "safer-buffer": "~2.1.0"
-            }
-        },
-        "assert-plus": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-            "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
-        },
         "assertion-error": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
@@ -4767,17 +4458,7 @@
         "asynckit": {
             "version": "0.4.0",
             "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-            "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
-        },
-        "aws-sign2": {
-            "version": "0.7.0",
-            "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-            "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
-        },
-        "aws4": {
-            "version": "1.8.0",
-            "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
-            "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
+            "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
         },
         "balanced-match": {
             "version": "1.0.0",
@@ -4789,14 +4470,6 @@
             "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz",
             "integrity": "sha1-Y5nVcuK8P5CpqLItXbsKMtM/eI0="
         },
-        "bcrypt-pbkdf": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-            "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
-            "requires": {
-                "tweetnacl": "^0.14.3"
-            }
-        },
         "binary-extensions": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@@ -4891,11 +4564,6 @@
             "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
             "dev": true
         },
-        "caseless": {
-            "version": "0.12.0",
-            "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
-        },
         "chai": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
@@ -5008,9 +4676,9 @@
             "dev": true
         },
         "combined-stream": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
-            "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+            "version": "1.0.8",
+            "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+            "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
             "requires": {
                 "delayed-stream": "~1.0.0"
             }
@@ -5041,11 +4709,6 @@
                 "safe-buffer": "~5.1.1"
             }
         },
-        "core-util-is": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-            "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
-        },
         "cross-spawn": {
             "version": "7.0.3",
             "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -5066,14 +4729,6 @@
                 }
             }
         },
-        "dashdash": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-            "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
-            "requires": {
-                "assert-plus": "^1.0.0"
-            }
-        },
         "debug": {
             "version": "4.3.4",
             "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -5138,7 +4793,7 @@
         "delayed-stream": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-            "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+            "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
         },
         "diff": {
             "version": "3.5.0",
@@ -5146,15 +4801,6 @@
             "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
             "dev": true
         },
-        "ecc-jsbn": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-            "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
-            "requires": {
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.1.0"
-            }
-        },
         "emoji-regex": {
             "version": "8.0.0",
             "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -5220,26 +4866,6 @@
                 "strip-final-newline": "^2.0.0"
             }
         },
-        "extend": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-            "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
-        },
-        "extsprintf": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-            "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
-        },
-        "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=="
-        },
-        "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=="
-        },
         "fill-range": {
             "version": "7.0.1",
             "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -5286,18 +4912,13 @@
                 "signal-exit": "^3.0.2"
             }
         },
-        "forever-agent": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-            "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
-        },
         "form-data": {
-            "version": "2.3.3",
-            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
-            "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+            "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
             "requires": {
                 "asynckit": "^0.4.0",
-                "combined-stream": "^1.0.6",
+                "combined-stream": "^1.0.8",
                 "mime-types": "^2.1.12"
             }
         },
@@ -5356,14 +4977,6 @@
             "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
             "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
         },
-        "getpass": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-            "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
-            "requires": {
-                "assert-plus": "^1.0.0"
-            }
-        },
         "glob": {
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
@@ -5416,20 +5029,6 @@
             "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
             "dev": true
         },
-        "har-schema": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-            "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
-        },
-        "har-validator": {
-            "version": "5.1.5",
-            "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
-            "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
-            "requires": {
-                "ajv": "^6.12.3",
-                "har-schema": "^2.0.0"
-            }
-        },
         "has-flag": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -5471,16 +5070,6 @@
             "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
             "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
         },
-        "http-signature": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-            "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
-            "requires": {
-                "assert-plus": "^1.0.0",
-                "jsprim": "^1.2.2",
-                "sshpk": "^1.7.0"
-            }
-        },
         "http2-wrapper": {
             "version": "1.0.0-beta.5.2",
             "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz",
@@ -5581,7 +5170,8 @@
         "is-typedarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+            "dev": true
         },
         "is-unicode-supported": {
             "version": "0.1.0",
@@ -5603,12 +5193,8 @@
         "isomorphic-ws": {
             "version": "4.0.1",
             "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
-            "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w=="
-        },
-        "isstream": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-            "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+            "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
+            "requires": {}
         },
         "istanbul-lib-coverage": {
             "version": "3.0.0",
@@ -5770,11 +5356,6 @@
                 }
             }
         },
-        "jsbn": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-            "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
-        },
         "jsesc": {
             "version": "2.5.2",
             "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@@ -5786,20 +5367,11 @@
             "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
             "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
         },
-        "json-schema": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
-            "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
-        },
-        "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=="
-        },
         "json-stringify-safe": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+            "dev": true
         },
         "json5": {
             "version": "2.2.3",
@@ -5818,17 +5390,6 @@
             "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-0.19.0.tgz",
             "integrity": "sha512-GSVwsrzW9LsA5lzsqe4CkuZ9wp+kxBb2GwNniaWzI2YFn5Ig42rSW8ZxVpWXaAfakXNrx5pgY5AbQq7kzX29kg=="
         },
-        "jsprim": {
-            "version": "1.4.2",
-            "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
-            "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
-            "requires": {
-                "assert-plus": "1.0.0",
-                "extsprintf": "1.3.0",
-                "json-schema": "0.4.0",
-                "verror": "1.10.0"
-            }
-        },
         "keyv": {
             "version": "4.5.2",
             "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
@@ -5959,16 +5520,16 @@
             "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
         },
         "mime-db": {
-            "version": "1.36.0",
-            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
-            "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw=="
+            "version": "1.52.0",
+            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+            "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
         },
         "mime-types": {
-            "version": "2.1.20",
-            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
-            "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
+            "version": "2.1.35",
+            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+            "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
             "requires": {
-                "mime-db": "~1.36.0"
+                "mime-db": "1.52.0"
             }
         },
         "mimic-fn": {
@@ -6300,11 +5861,6 @@
                 }
             }
         },
-        "oauth-sign": {
-            "version": "0.9.0",
-            "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
-            "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
-        },
         "object-hash": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz",
@@ -6472,11 +6028,6 @@
             "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
             "dev": true
         },
-        "performance-now": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-            "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
-        },
         "picomatch": {
             "version": "2.3.1",
             "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
@@ -6542,11 +6093,6 @@
             "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
             "dev": true
         },
-        "psl": {
-            "version": "1.1.29",
-            "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
-            "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
-        },
         "pump": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@@ -6556,16 +6102,6 @@
                 "once": "^1.3.1"
             }
         },
-        "punycode": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-            "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
-        },
-        "qs": {
-            "version": "6.5.3",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
-            "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA=="
-        },
         "querystringify": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
@@ -6611,33 +6147,6 @@
                 "es6-error": "^4.0.1"
             }
         },
-        "request": {
-            "version": "2.88.0",
-            "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
-            "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
-            "requires": {
-                "aws-sign2": "~0.7.0",
-                "aws4": "^1.8.0",
-                "caseless": "~0.12.0",
-                "combined-stream": "~1.0.6",
-                "extend": "~3.0.2",
-                "forever-agent": "~0.6.1",
-                "form-data": "~2.3.2",
-                "har-validator": "~5.1.0",
-                "http-signature": "~1.2.0",
-                "is-typedarray": "~1.0.0",
-                "isstream": "~0.1.2",
-                "json-stringify-safe": "~5.0.1",
-                "mime-types": "~2.1.19",
-                "oauth-sign": "~0.9.0",
-                "performance-now": "^2.1.0",
-                "qs": "~6.5.2",
-                "safe-buffer": "^5.1.2",
-                "tough-cookie": "~2.4.3",
-                "tunnel-agent": "^0.6.0",
-                "uuid": "^3.3.2"
-            }
-        },
         "require-directory": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -6692,12 +6201,8 @@
         "safe-buffer": {
             "version": "5.1.2",
             "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-            "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
-        },
-        "safer-buffer": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-            "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+            "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+            "dev": true
         },
         "semver": {
             "version": "5.5.1",
@@ -6815,22 +6320,6 @@
             "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
             "dev": true
         },
-        "sshpk": {
-            "version": "1.15.1",
-            "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz",
-            "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==",
-            "requires": {
-                "asn1": "~0.2.3",
-                "assert-plus": "^1.0.0",
-                "bcrypt-pbkdf": "^1.0.0",
-                "dashdash": "^1.12.0",
-                "ecc-jsbn": "~0.1.1",
-                "getpass": "^0.1.1",
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.0.2",
-                "tweetnacl": "~0.14.0"
-            }
-        },
         "stream-buffers": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz",
@@ -6957,15 +6446,6 @@
                 "is-number": "^7.0.0"
             }
         },
-        "tough-cookie": {
-            "version": "2.4.3",
-            "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
-            "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
-            "requires": {
-                "psl": "^1.1.24",
-                "punycode": "^1.4.1"
-            }
-        },
         "tr46": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -7048,19 +6528,6 @@
                 "tslib": "^1.8.1"
             }
         },
-        "tunnel-agent": {
-            "version": "0.6.0",
-            "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
-            "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
-            "requires": {
-                "safe-buffer": "^5.0.1"
-            }
-        },
-        "tweetnacl": {
-            "version": "0.14.5",
-            "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-            "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
-        },
         "type-detect": {
             "version": "4.0.8",
             "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
@@ -7119,21 +6586,6 @@
             "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
             "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw=="
         },
-        "uri-js": {
-            "version": "4.4.1",
-            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-            "requires": {
-                "punycode": "^2.1.0"
-            },
-            "dependencies": {
-                "punycode": {
-                    "version": "2.3.0",
-                    "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
-                    "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="
-                }
-            }
-        },
         "url-parse": {
             "version": "1.5.10",
             "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
@@ -7143,21 +6595,6 @@
                 "requires-port": "^1.0.0"
             }
         },
-        "uuid": {
-            "version": "3.3.2",
-            "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
-            "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
-        },
-        "verror": {
-            "version": "1.10.0",
-            "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
-            "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
-            "requires": {
-                "assert-plus": "^1.0.0",
-                "core-util-is": "1.0.2",
-                "extsprintf": "^1.2.0"
-            }
-        },
         "vscode-oniguruma": {
             "version": "1.7.0",
             "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
diff --git a/package.json b/package.json
index 7a3e8641..9615c21d 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,7 @@
     "dependencies": {
         "@types/js-yaml": "^4.0.1",
         "@types/node": "^10.12.0",
-        "@types/request": "^2.47.1",
+        "@types/node-fetch": "^2.6.3",
         "@types/stream-buffers": "^3.0.3",
         "@types/tar": "^6.1.1",
         "@types/underscore": "^1.8.9",
@@ -64,12 +64,12 @@
         "abort-controller": "^3.0.0",
         "byline": "^5.0.0",
         "execa": "5.0.0",
+        "form-data": "^4.0.0",
         "isomorphic-ws": "^4.0.1",
         "js-yaml": "^4.1.0",
         "jsonpath-plus": "^0.19.0",
-        "node-fetch": "^2.6.0",
+        "node-fetch": "^2.6.9",
         "openid-client": "^4.1.1",
-        "request": "^2.88.0",
         "rfc4648": "^1.3.0",
         "shelljs": "^0.8.5",
         "stream-buffers": "^3.0.2",
diff --git a/src/cache.ts b/src/cache.ts
index ac08df85..db36594e 100644
--- a/src/cache.ts
+++ b/src/cache.ts
@@ -1,3 +1,4 @@
+import AbortController from 'abort-controller';
 import {
     ADD,
     CHANGE,
@@ -12,7 +13,7 @@ import {
 } from './informer';
 import { KubernetesObject } from './types';
 import { ObjectSerializer } from './util';
-import { RequestResult, Watch } from './watch';
+import { Watch } from './watch';
 
 export interface ObjectCache<T> {
     get(name: string, namespace?: string): T | undefined;
@@ -25,7 +26,7 @@ export class ListWatch<T extends KubernetesObject> implements ObjectCache<T>, In
     private resourceVersion: string;
     private readonly indexCache: { [key: string]: T[] } = {};
     private readonly callbackCache: { [key: string]: Array<ObjectCallback<T> | ErrorCallback> } = {};
-    private request: RequestResult | undefined;
+    private request: AbortController | undefined;
     private stopped: boolean = false;
 
     public constructor(
diff --git a/src/config.ts b/src/config.ts
index 7743087e..7e0a2063 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -7,6 +7,7 @@ import path = require('path');
 
 import shelljs = require('shelljs');
 
+import { Headers, RequestInit } from 'node-fetch';
 import * as api from './api';
 import { Authenticator } from './auth';
 import { AzureAuth } from './azure_auth';
@@ -146,6 +147,29 @@ export class KubeConfig implements SecurityAuthentication {
         this.makePathsAbsolute(rootDirectory);
     }
 
+    public async applytoFetchOptions(opts: https.RequestOptions): Promise<RequestInit> {
+        await this.applytoHTTPSOptions(opts);
+        const headers = new Headers();
+        for (const [key, val] of Object.entries(opts.headers || {})) {
+            if (Array.isArray(val)) {
+                val.forEach((innerVal) => {
+                    headers.append(key, innerVal);
+                });
+            } else if (typeof val === 'number' || typeof val === 'string') {
+                headers.set(key, val.toString());
+            }
+        }
+        if (opts.auth) {
+            headers.set('Authorization', 'Basic ' + Buffer.from(opts.auth).toString('base64'));
+        }
+        return {
+            agent: opts.agent,
+            headers,
+            method: opts.method,
+            timeout: opts.timeout,
+        };
+    }
+
     public async applytoHTTPSOptions(opts: https.RequestOptions): Promise<void> {
         const user = this.getCurrentUser();
 
@@ -164,6 +188,17 @@ export class KubeConfig implements SecurityAuthentication {
         agentOptions.pfx = opts.pfx;
         agentOptions.passphrase = opts.passphrase;
         agentOptions.rejectUnauthorized = opts.rejectUnauthorized;
+        agentOptions.timeout = opts.timeout;
+        agentOptions.servername = opts.servername;
+        agentOptions.ciphers = opts.ciphers;
+        agentOptions.honorCipherOrder = opts.honorCipherOrder;
+        agentOptions.ecdhCurve = opts.ecdhCurve;
+        agentOptions.clientCertEngine = opts.clientCertEngine;
+        agentOptions.crl = opts.crl;
+        agentOptions.dhparam = opts.dhparam;
+        agentOptions.secureOptions = opts.secureOptions;
+        agentOptions.secureProtocol = opts.secureProtocol;
+        agentOptions.sessionIdContext = opts.sessionIdContext;
 
         opts.agent = new https.Agent(agentOptions);
     }
diff --git a/src/gen/apis/exception.ts b/src/gen/apis/exception.ts
index 9365d33a..3c8f7bc8 100644
--- a/src/gen/apis/exception.ts
+++ b/src/gen/apis/exception.ts
@@ -8,7 +8,7 @@
  *
  */
 export class ApiException<T> extends Error {
-    public constructor(public code: number, message: string, public body: T, public headers: { [key: string]: string; }) {
+    public constructor(public code: number, message: string, public body: T, public headers: { [key: string]: string | string[]; }) {
         super("HTTP-Code: " + code + "\nMessage: " + message + "\nBody: " + JSON.stringify(body) + "\nHeaders: " +
         JSON.stringify(headers))
     }
diff --git a/src/log.ts b/src/log.ts
index 7cbd174d..c33d07ff 100644
--- a/src/log.ts
+++ b/src/log.ts
@@ -1,6 +1,6 @@
+import AbortController from 'abort-controller';
 import { RequestOptions } from 'https';
 import fetch from 'node-fetch';
-import request = require('request');
 import { Writable } from 'stream';
 import { URL, URLSearchParams } from 'url';
 import { ApiException } from './api';
@@ -83,7 +83,7 @@ export class Log {
         containerName: string,
         stream: Writable,
         options?: LogOptions,
-    ): Promise<request.Request>;
+    ): Promise<AbortController>;
     /** @deprecated done callback is deprecated */
     public async log(
         namespace: string,
@@ -92,7 +92,7 @@ export class Log {
         stream: Writable,
         done: (err: any) => void,
         options?: LogOptions,
-    ): Promise<request.Request>;
+    ): Promise<AbortController>;
     public async log(
         namespace: string,
         podName: string,
@@ -100,11 +100,10 @@ export class Log {
         stream: Writable,
         doneOrOptions?: ((err: any) => void) | LogOptions,
         options?: LogOptions,
-    ): Promise<request.Request> {
-        let done: (err: any) => void = () => undefined;
-        if (typeof doneOrOptions === 'function') {
-            done = doneOrOptions;
-        } else {
+    ): Promise<AbortController> {
+        const AbortControllerCtor = globalThis.AbortController || (await import('abort-controller'));
+
+        if (typeof doneOrOptions !== 'function') {
             options = doneOrOptions;
         }
 
@@ -114,18 +113,20 @@ export class Log {
         if (!cluster) {
             throw new Error('No currently active cluster');
         }
-        const url = cluster.server + path;
-
-        const requestOptions: RequestOptions = {};
 
         const requestURL = new URL(cluster.server + path);
 
         const searchParams = requestURL.searchParams;
+        searchParams.set('container', containerName);
         AddOptionsToSearchParams(options, searchParams);
 
-        await this.config.applytoHTTPSOptions(requestOptions);
+        const requestInit = await this.config.applytoFetchOptions({});
 
-        const req = await fetch(requestURL.toString(), requestOptions)
+        const controller = new AbortControllerCtor();
+        requestInit.signal = controller.signal;
+        requestInit.method = 'GET';
+
+        await fetch(requestURL.toString(), requestInit)
             .then((response) => {
                 const status = response.status;
                 if (status === 200) {
@@ -155,6 +156,7 @@ export class Log {
             .catch((err) => {
                 throw new ApiException<undefined>(err, 'Error occurred in log request', undefined, err);
             });
-        return req;
+
+        return controller;
     }
 }
diff --git a/src/metrics.ts b/src/metrics.ts
index 64f3cf5b..73188564 100644
--- a/src/metrics.ts
+++ b/src/metrics.ts
@@ -1,4 +1,3 @@
-import { RequestOptions } from 'https';
 import fetch from 'node-fetch';
 import { KubeConfig } from './config';
 import { ApiException, V1Status } from './gen';
@@ -83,16 +82,12 @@ export class Metrics {
             throw new Error('No currently active cluster');
         }
 
-        const requestOptions: RequestOptions = {
-            method: 'GET',
-            servername: cluster.server + path,
-        };
-
         const requestURL = cluster.server + path;
 
-        await this.config.applytoHTTPSOptions(requestOptions);
+        const requestInit = await this.config.applytoFetchOptions({});
+        requestInit.method = 'GET';
 
-        return fetch(requestURL, requestOptions)
+        return fetch(requestURL, requestInit)
             .then((response) => {
                 return Promise.all([response.json(), response.status, response]);
             })
diff --git a/src/watch.ts b/src/watch.ts
index 29cd8849..bd835ad7 100644
--- a/src/watch.ts
+++ b/src/watch.ts
@@ -2,76 +2,15 @@ import AbortController from 'abort-controller';
 import byline = require('byline');
 import { RequestOptions } from 'https';
 import fetch from 'node-fetch';
-import request = require('request');
-import { Duplex } from 'stream';
 import { URL } from 'url';
 import { KubeConfig } from './config';
 
-export interface WatchUpdate {
-    type: string;
-    object: object;
-}
-
-// We cannot use the type ReadableStream because Request returned by request
-// library is not a true ReadableStream and there is extra abort method.
-export interface RequestResult {
-    pipe(stream: Duplex): void;
-    on(ev: string, cb: (arg: any) => void): void;
-    abort(): void;
-}
-
-export interface Response {
-    statusCode: number;
-    statusMessage: string;
-}
-
-// The contract is that the provided request library will return a readable
-// stream with abort method.
-export interface RequestInterface {
-    webRequest(opts: request.OptionsWithUri): RequestResult;
-}
-
-export class DefaultRequest implements RequestInterface {
-    // requestImpl can be overriden in case we need to test mocked DefaultRequest
-    private requestImpl: (opts: request.OptionsWithUri) => request.Request;
-
-    constructor(requestImpl?: (opts: request.OptionsWithUri) => request.Request) {
-        this.requestImpl = requestImpl ? requestImpl : request;
-    }
-
-    // Using request lib can be confusing when combining Stream- with Callback-
-    // style API. We avoid the callback and handle HTTP response errors, that
-    // would otherwise require a different error handling, in a transparent way
-    // to the user (see github issue request/request#647 for more info).
-    public webRequest(opts: request.OptionsWithUri): RequestResult {
-        const req = this.requestImpl(opts);
-        // pause the stream until we get a response not to miss any bytes
-        req.pause();
-        req.on('response', (resp) => {
-            if (resp.statusCode === 200) {
-                req.resume();
-            } else {
-                const error = new Error(resp.statusMessage) as Error & { statusCode: number | undefined };
-                error.statusCode = resp.statusCode;
-                req.emit('error', error);
-            }
-        });
-        return req;
-    }
-}
-
 export class Watch {
     public static SERVER_SIDE_CLOSE: object = { error: 'Connection closed on server' };
     public config: KubeConfig;
-    private readonly requestImpl: RequestInterface;
 
-    public constructor(config: KubeConfig, requestImpl?: RequestInterface) {
+    public constructor(config: KubeConfig) {
         this.config = config;
-        if (requestImpl) {
-            this.requestImpl = requestImpl;
-        } else {
-            this.requestImpl = new DefaultRequest();
-        }
     }
 
     // Watch the resource and call provided callback with parsed json object
@@ -82,10 +21,13 @@ export class Watch {
     // underlaying connection so that it doesn't leak any resources.
     public async watch(
         path: string,
-        queryParams: any,
+        queryParams: Record<string, string | number | boolean | undefined>,
         callback: (phase: string, apiObj: any, watchObj?: any) => void,
         done: (err: any) => void,
-    ): Promise<any> {
+    ): Promise<AbortController> {
+        const AbortControllerCtor =
+            globalThis.AbortController || (await import('abort-controller')).AbortController;
+
         const cluster = this.config.getCurrentCluster();
         if (!cluster) {
             throw new Error('No currently active cluster');
@@ -93,13 +35,17 @@ export class Watch {
         const watchURL = new URL(cluster.server + path);
         watchURL.searchParams.set('watch', 'true');
 
-        const httpsOptions: RequestOptions = {};
-        // TODO: fix applytoHTTPSOptions for watch
-        await this.config.applytoHTTPSOptions(httpsOptions);
+        for (const [key, val] of Object.entries(queryParams || {})) {
+            if (val !== undefined) {
+                watchURL.searchParams.set(key, val.toString());
+            }
+        }
 
-        const controller = new AbortController();
-        // @ts-ignore
-        httpsOptions.signal = controller.signal;
+        const requestInit = await this.config.applytoFetchOptions({});
+
+        const controller = new AbortControllerCtor();
+        requestInit.signal = controller.signal;
+        requestInit.method = 'GET';
 
         let doneCalled: boolean = false;
         const doneCallOnce = (err: any) => {
@@ -112,6 +58,7 @@ export class Watch {
         const stream = byline.createStream();
         stream.on('error', doneCallOnce);
         stream.on('close', () => doneCallOnce(null));
+        stream.on('finish', () => doneCallOnce(null));
         stream.on('data', (line) => {
             try {
                 const data = JSON.parse(line.toString());
@@ -121,11 +68,23 @@ export class Watch {
             }
         });
 
-        const req = await fetch(watchURL, httpsOptions)
+        await fetch(watchURL, requestInit)
             .then((response) => {
-                response.body.pipe(stream);
+                if (response.status === 200) {
+                    response.body.on('error', doneCallOnce);
+                    response.body.on('close', () => doneCallOnce(null));
+                    response.body.on('finish', () => doneCallOnce(null));
+                    response.body.pipe(stream);
+                } else {
+                    const error = new Error(response.statusText) as Error & {
+                        statusCode: number | undefined;
+                    };
+                    error.statusCode = response.status;
+                    throw error;
+                }
             })
             .catch(doneCallOnce);
-        return req;
+
+        return controller;
     }
 }


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e3c558d4..02e4ac63 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -11,7 +11,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        node: [ '16', '14', '12' ]
+        node: [ '18', '16', '14', '12' ]
     name: Node ${{ matrix.node }} validation
     steps:
       - uses: actions/checkout@v2
diff --git a/src/cache_test.ts b/src/cache_test.ts
index 045a6dd2..49c13dd0 100644
--- a/src/cache_test.ts
+++ b/src/cache_test.ts
@@ -1,30 +1,23 @@
 import { expect, use } from 'chai';
-import * as request from 'request';
 import chaiAsPromised = require('chai-as-promised');
 
 import * as mock from 'ts-mockito';
 
 import http = require('http');
-import { Duplex } from 'stream';
-import { EventEmitter } from 'ws';
 
-import { V1Namespace, V1NamespaceList, V1ObjectMeta, V1Pod, V1ListMeta } from './api';
-import { deleteObject, ListWatch, deleteItems } from './cache';
+import { V1ListMeta, V1Namespace, V1NamespaceList, V1ObjectMeta, V1Pod } from './api';
+import { deleteItems, deleteObject, ListWatch } from './cache';
 import { KubeConfig } from './config';
 import { Cluster, Context, User } from './config_types';
-import { ADD, UPDATE, DELETE, ERROR, ListPromise, CHANGE } from './informer';
+import { ListPromise } from './informer';
 
 use(chaiAsPromised);
 
-import { DefaultRequest, RequestResult, Watch } from './watch';
+import AbortController from 'abort-controller';
+import nock = require('nock');
+import { Watch } from './watch';
 
-// Object replacing real Request object in the test
-class FakeRequest extends EventEmitter implements RequestResult {
-    pipe(stream: Duplex): void {}
-    abort() {}
-}
-
-const server = 'foo.company.com';
+const server = 'http://foo.company.com';
 
 const fakeConfig: {
     clusters: Cluster[];
@@ -115,7 +108,7 @@ describe('ListWatchCache', () => {
             ],
         } as V1NamespaceList;
 
-        var calls = 0;
+        let calls = 0;
         const listFn: ListPromise<V1Namespace> = function (): Promise<{
             response: http.IncomingMessage;
             body: V1NamespaceList;
@@ -134,7 +127,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         const cache = new ListWatch('/some/path', mock.instance(fakeWatch), listFn);
@@ -240,7 +233,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         const informer = new ListWatch('/some/path', mock.instance(fakeWatch), listFn);
@@ -329,7 +322,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         const informer = new ListWatch('/some/path', mock.instance(fakeWatch), listFn);
@@ -392,7 +385,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         const informer = new ListWatch('/some/path', mock.instance(fakeWatch), listFn);
@@ -461,7 +454,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         const informer = new ListWatch('/some/path', mock.instance(fakeWatch), listFn, false);
@@ -483,7 +476,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         doneHandler(null);
@@ -537,7 +530,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         const informer = new ListWatch('/some/path', mock.instance(fakeWatch), listFn, false);
@@ -560,7 +553,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         listObj.items = list2;
@@ -617,7 +610,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         const cache = new ListWatch('/some/path', mock.instance(fakeWatch), listFn);
@@ -962,11 +955,11 @@ describe('ListWatchCache', () => {
                 },
             );
         };
-        let promise = new Promise((resolve) => {
+        const promise = new Promise((resolve) => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
 
@@ -1025,11 +1018,11 @@ describe('ListWatchCache', () => {
                 },
             );
         };
-        let promise = new Promise((resolve) => {
+        const promise = new Promise((resolve) => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
 
@@ -1074,7 +1067,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         const informer = new ListWatch('/some/path', mock.instance(fakeWatch), listFn, false);
@@ -1098,7 +1091,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
         informer.start();
@@ -1130,7 +1123,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
 
@@ -1159,7 +1152,7 @@ describe('ListWatchCache', () => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
 
@@ -1179,7 +1172,7 @@ describe('ListWatchCache', () => {
         expect(listCalls).to.be.equal(2);
     });
 
-    it.skip('should send label selector', async () => {
+    it('should send label selector', async () => {
         const APP_LABEL_SELECTOR = 'app=foo';
 
         const list: V1Namespace[] = [
@@ -1220,20 +1213,57 @@ describe('ListWatchCache', () => {
 
         const kc = new KubeConfig();
         Object.assign(kc, fakeConfig);
-        const fakeRequestor = mock.mock(DefaultRequest);
-        const watch = new Watch(kc, mock.instance(fakeRequestor));
+        const watch = new Watch(kc);
 
-        const fakeRequest = new FakeRequest();
-        mock.when(fakeRequestor.webRequest(mock.anything())).thenReturn(fakeRequest);
+        const path = '/some/path';
 
-        const informer = new ListWatch('/some/path', watch, listFn, false, APP_LABEL_SELECTOR);
+        const informer = new ListWatch(path, watch, listFn, false, APP_LABEL_SELECTOR);
+
+        const scope = nock(fakeConfig.clusters[0].server);
+        const s = scope
+            .get(path)
+            .query({
+                watch: true,
+                resourceVersion: '12345',
+                labelSelector: APP_LABEL_SELECTOR,
+            })
+            .reply(
+                200,
+                () =>
+                    JSON.stringify({
+                        type: 'ADDED',
+                        object: {
+                            metadata: {
+                                name: 'name3',
+                                labels: {
+                                    app: 'foo3',
+                                },
+                            } as V1ObjectMeta,
+                        },
+                    }) + '\n',
+            );
 
         await informer.start();
 
-        mock.verify(fakeRequestor.webRequest(mock.anything()));
-        const [opts] = mock.capture(fakeRequestor.webRequest).last();
-        const reqOpts: request.OptionsWithUri = opts as request.OptionsWithUri;
-        expect(reqOpts.qs.labelSelector).to.equal(APP_LABEL_SELECTOR);
+        let doneResolve: any;
+        const donePromise = new Promise((resolve) => {
+            doneResolve = resolve;
+        });
+
+        informer.on('add', doneResolve);
+
+        const value = await donePromise;
+
+        expect(value).to.deep.equal({
+            metadata: {
+                labels: {
+                    app: 'foo3',
+                },
+                name: 'name3',
+            },
+        });
+
+        s.done();
     });
 });
 
@@ -1344,11 +1374,11 @@ describe('delete items', () => {
                 },
             );
         };
-        let promise = new Promise((resolve) => {
+        const promise = new Promise((resolve) => {
             mock.when(
                 fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
             ).thenCall(() => {
-                resolve(new FakeRequest());
+                resolve(new AbortController());
             });
         });
 
diff --git a/src/config_test.ts b/src/config_test.ts
index 6175dae3..97b2539b 100644
--- a/src/config_test.ts
+++ b/src/config_test.ts
@@ -1,19 +1,20 @@
 import { readFileSync } from 'fs';
 import * as https from 'https';
+import { Agent, RequestOptions } from 'https';
 import { join } from 'path';
-import { RequestOptions } from 'https';
 
 import { expect, use } from 'chai';
 import chaiAsPromised from 'chai-as-promised';
 import mockfs = require('mock-fs');
 import * as path from 'path';
 
+import { Headers } from 'node-fetch';
+import { HttpMethod } from '.';
+import { assertRequestAgentsEqual, assertRequestOptionsEqual } from '../test/match-buffer';
 import { CoreV1Api, RequestContext } from './api';
 import { bufferFromFileOrString, findHomeDir, findObject, KubeConfig, makeAbsolutePath } from './config';
-import { Cluster, newClusters, newContexts, newUsers, User, ActionOnInvalid } from './config_types';
+import { ActionOnInvalid, Cluster, newClusters, newContexts, newUsers, User } from './config_types';
 import { ExecAuth } from './exec_auth';
-import { HttpMethod } from '.';
-import { assertRequestOptionsEqual } from '../test/match-buffer';
 
 const kcFileName = 'testdata/kubeconfig.yaml';
 const kc2FileName = 'testdata/kubeconfig-2.yaml';
@@ -237,6 +238,41 @@ describe('KubeConfig', () => {
         });
     });
 
+    describe('applytoFetchOptions', () => {
+        it('should apply cert configs', async () => {
+            const kc = new KubeConfig();
+            kc.loadFromFile(kcFileName);
+            kc.setCurrentContext('passwd');
+
+            const opts: https.RequestOptions = {
+                method: 'POST',
+                timeout: 5,
+                headers: {
+                    number: 5,
+                    string: 'str',
+                    empty: undefined,
+                    list: ['a', 'b'],
+                },
+            };
+            const requestInit = await kc.applytoFetchOptions(opts);
+            const expectedCA = Buffer.from('CADATA2', 'utf-8');
+            const expectedAgent = new https.Agent({
+                ca: expectedCA,
+                rejectUnauthorized: false,
+            });
+
+            expect(requestInit.method).to.equal('POST');
+            expect(requestInit.timeout).to.equal(5);
+            expect((requestInit.headers as Headers).raw()).to.deep.equal({
+                Authorization: ['Basic Zm9vOmJhcg=='],
+                list: ['a', 'b'],
+                number: ['5'],
+                string: ['str'],
+            });
+            assertRequestAgentsEqual(requestInit.agent as Agent, expectedAgent);
+        });
+    });
+
     describe('applyHTTPSOptions', () => {
         it('should apply cert configs', () => {
             const kc = new KubeConfig();
@@ -274,7 +310,7 @@ describe('KubeConfig', () => {
                 pfx: undefined,
                 rejectUnauthorized: false,
             });
-            let expectedOptions: https.RequestOptions = {
+            const expectedOptions: https.RequestOptions = {
                 auth: 'foo:bar',
                 headers: {},
                 rejectUnauthorized: false,
@@ -1138,10 +1174,10 @@ describe('KubeConfig', () => {
             // TODO: inject the exec command here?
             const opts = {} as RequestOptions;
             await config.applytoHTTPSOptions(opts);
-            let execAuthenticator = (KubeConfig as any).authenticators.find(
+            const execAuthenticator = (KubeConfig as any).authenticators.find(
                 (authenticator) => authenticator instanceof ExecAuth,
             );
-            expect(execAuthenticator.tokenCache['exec']).to.deep.equal(JSON.parse(responseStr));
+            expect(execAuthenticator.tokenCache.exec).to.deep.equal(JSON.parse(responseStr));
         });
 
         it('should throw with no command.', () => {
@@ -1231,7 +1267,7 @@ describe('KubeConfig', () => {
             const kc = new KubeConfig();
             kc.addCluster({
                 name: 'testCluster',
-                server: `https://localhost:9889`,
+                server: 'https://localhost:9889',
                 skipTLSVerify: true,
                 caFile: 'foo/bar.crt',
             });
@@ -1467,7 +1503,7 @@ describe('KubeConfig', () => {
             (kc as any).clusters = undefined;
             kc.addCluster({
                 name: 'testCluster',
-                server: `https://localhost:9889`,
+                server: 'https://localhost:9889',
                 skipTLSVerify: true,
             });
             (kc as any).users = undefined;
diff --git a/src/watch_test.ts b/src/watch_test.ts
index a06a662b..117f5a6e 100644
--- a/src/watch_test.ts
+++ b/src/watch_test.ts
@@ -1,14 +1,14 @@
 import { expect } from 'chai';
-import request = require('request');
-import { Duplex } from 'stream';
-import { anything, capture, instance, mock, spy, verify, when } from 'ts-mockito';
-import { EventEmitter } from 'ws';
+// import { anything, capture, instance, mock, spy, verify, when } from 'ts-mockito';
 
+import nock = require('nock');
+import { PassThrough } from 'stream';
 import { KubeConfig } from './config';
 import { Cluster, Context, User } from './config_types';
-import { DefaultRequest, RequestResult, Watch } from './watch';
+import { Watch } from './watch';
+import { IncomingMessage } from 'http';
 
-const server = 'foo.company.com';
+const server = 'http://foo.company.com';
 
 const fakeConfig: {
     clusters: Cluster[];
@@ -34,81 +34,26 @@ const fakeConfig: {
     ],
 };
 
-// Object replacing real Request object in the test
-class FakeRequest extends EventEmitter implements RequestResult {
-    pipe(stream: Duplex): void {}
-    abort() {}
-}
+const systemUnderTest = (): [nock.Scope] => {
+    const scope = nock(fakeConfig.clusters[0].server);
+    return [scope];
+};
 
 describe('Watch', () => {
-    describe('DefaultRequest', () => {
-        it('should resume stream upon http status 200', (done) => {
-            const defaultRequest = new DefaultRequest((opts) => {
-                const req = request(opts);
-                // to prevent request from firing we must replace start() method
-                // before "nextTick" happens
-                (<any>req).start = () => {};
-                (<any>req).resume = () => done();
-                return req;
-            });
-            const req = defaultRequest.webRequest({
-                uri: `http://${server}/testURI`,
-            });
-            req.on('error', done);
-            (<any>req).emit('response', {
-                statusCode: 200,
-            });
-        });
-
-        it('should handle non-200 error codes', (done) => {
-            const defaultRequest = new DefaultRequest((opts) => {
-                const req = request(opts);
-                (<any>req).start = () => {};
-                return req;
-            });
-            const req = defaultRequest.webRequest({
-                uri: `http://${server}/testURI`,
-            });
-            req.on('error', (err) => {
-                expect(err.toString()).to.equal('Error: Conflict');
-                done();
-            });
-            (<any>req).emit('response', {
-                statusCode: 409,
-                statusMessage: 'Conflict',
-            });
-        });
-    });
-
     it('should construct correctly', () => {
         const kc = new KubeConfig();
         const watch = new Watch(kc);
     });
 
-    it.skip('should handle error from request stream', async () => {
+    it('should handle error from request stream', async () => {
         const kc = new KubeConfig();
-        const fakeRequest = new FakeRequest();
-        const spiedRequest = spy(fakeRequest);
-        let aborted = false;
+        const path = '/some/path/to/object?watch=true';
 
-        when(spiedRequest.pipe(anything())).thenCall(() => {
-            fakeRequest.emit('error', new Error('some error'));
-        });
-        when(spiedRequest.abort()).thenCall(() => {
-            aborted = true;
-        });
+        const [scope] = systemUnderTest();
+        const s = scope.get(path).reply(500, 'Error: some error');
 
         Object.assign(kc, fakeConfig);
-        const watch = new Watch(kc, {
-            webRequest: (opts: request.OptionsWithUri) => {
-                expect(opts.uri).to.equal(`${server}${path}`);
-                expect(opts.method).to.equal('GET');
-                expect(opts.json).to.equal(true);
-                return fakeRequest;
-            },
-        });
-
-        const path = '/some/path/to/object';
+        const watch = new Watch(kc);
 
         let doneCalled = false;
         let doneErr: any;
@@ -116,6 +61,7 @@ describe('Watch', () => {
         await watch.watch(
             path,
             {},
+            // tslint:disable-next-line:no-empty
             (phase: string, obj: string) => {},
             (err: any) => {
                 doneCalled = true;
@@ -123,15 +69,14 @@ describe('Watch', () => {
             },
         );
         expect(doneCalled).to.equal(true);
-        expect(doneErr.toString()).to.equal('Error: some error');
-        expect(aborted).to.equal(true);
+        expect(doneErr.toString()).to.equal('Error: Internal Server Error');
+        s.done();
     });
 
-    it.skip('should not call watch done callback more than once', async () => {
+    it('should not call watch done callback more than once', async () => {
         const kc = new KubeConfig();
         Object.assign(kc, fakeConfig);
-        const fakeRequestor = mock(DefaultRequest);
-        const watch = new Watch(kc, instance(fakeRequestor));
+        const watch = new Watch(kc);
 
         const obj1 = {
             type: 'ADDED',
@@ -147,64 +92,87 @@ describe('Watch', () => {
             },
         };
 
-        var stream;
-        const fakeRequest = new FakeRequest();
-        fakeRequest.pipe = function (arg) {
-            stream = arg;
-            stream.write(JSON.stringify(obj1) + '\n');
-            stream.write(JSON.stringify(obj2) + '\n');
-        };
-
-        when(fakeRequestor.webRequest(anything())).thenReturn(fakeRequest);
-
         const path = '/some/path/to/object';
 
+        const stream = new PassThrough();
+
+        const [scope] = systemUnderTest();
+
+        let response: IncomingMessage | undefined;
+
+        const s = scope
+            .get(path)
+            .query({
+                watch: 'true',
+                a: 'b',
+            })
+            .reply(200, function (): PassThrough {
+                this.req.on('response', (r) => {
+                    response = r;
+                });
+                stream.push(JSON.stringify(obj1) + '\n');
+                stream.push(JSON.stringify(obj2) + '\n');
+                return stream;
+            });
+
         const receivedTypes: string[] = [];
         const receivedObjects: string[] = [];
         let doneCalled = 0;
         let doneErr: any;
 
+        let handledAllObjectsResolve: any;
+        const handledAllObjectsPromise = new Promise((resolve) => {
+            handledAllObjectsResolve = resolve;
+        });
+
+        let doneResolve: any;
+        const donePromise = new Promise((resolve) => {
+            doneResolve = resolve;
+        });
+
         await watch.watch(
             path,
-            {},
+            {
+                a: 'b',
+            },
             (phase: string, obj: string) => {
                 receivedTypes.push(phase);
                 receivedObjects.push(obj);
+                if (receivedObjects.length === 2) {
+                    handledAllObjectsResolve();
+                }
             },
             (err: any) => {
                 doneCalled += 1;
                 doneErr = err;
+                doneResolve();
             },
         );
 
-        verify(fakeRequestor.webRequest(anything()));
-
-        const [opts] = capture(fakeRequestor.webRequest).last();
-        const reqOpts: request.OptionsWithUri = opts as request.OptionsWithUri;
-
-        expect(reqOpts.uri).to.equal(`${server}${path}`);
-        expect(reqOpts.method).to.equal('GET');
-        expect(reqOpts.json).to.equal(true);
+        await handledAllObjectsPromise;
 
         expect(receivedTypes).to.deep.equal([obj1.type, obj2.type]);
         expect(receivedObjects).to.deep.equal([obj1.object, obj2.object]);
 
         expect(doneCalled).to.equal(0);
 
-        const errIn = { error: 'err' };
-        stream.emit('error', errIn);
-        expect(doneErr).to.deep.equal(errIn);
-        expect(doneCalled).to.equal(1);
+        const errIn = new Error('err');
+        (response as IncomingMessage).socket.destroy(errIn);
+
+        await donePromise;
 
-        stream.end();
         expect(doneCalled).to.equal(1);
+        expect(doneErr).to.deep.equal(errIn);
+
+        s.done();
+
+        stream.destroy();
     });
 
-    it.skip('should handle errors correctly', async () => {
+    it('should handle server errors correctly', async () => {
         const kc = new KubeConfig();
         Object.assign(kc, fakeConfig);
-        const fakeRequestor = mock(DefaultRequest);
-        const watch = new Watch(kc, instance(fakeRequestor));
+        const watch = new Watch(kc);
 
         const obj1 = {
             type: 'ADDED',
@@ -213,22 +181,35 @@ describe('Watch', () => {
             },
         };
 
-        const errIn = { error: 'err' };
-        const fakeRequest = new FakeRequest();
-        fakeRequest.pipe = function (stream) {
-            stream.write(JSON.stringify(obj1) + '\n');
-            stream.emit('error', errIn);
-            stream.emit('close');
-        };
+        const stream = new PassThrough();
 
-        when(fakeRequestor.webRequest(anything())).thenReturn(fakeRequest);
+        const [scope] = systemUnderTest();
 
-        const path = '/some/path/to/object';
+        const path = '/some/path/to/object?watch=true';
+
+        let response: IncomingMessage | undefined;
+
+        const s = scope.get(path).reply(200, function (): PassThrough {
+            this.req.on('response', (r) => {
+                response = r;
+            });
+            stream.push(JSON.stringify(obj1) + '\n');
+            return stream;
+        });
 
         const receivedTypes: string[] = [];
         const receivedObjects: string[] = [];
-        let doneCalled = false;
-        let doneErr: any[] = [];
+        const doneErr: any[] = [];
+
+        let handledAllObjectsResolve: any;
+        const handledAllObjectsPromise = new Promise((resolve) => {
+            handledAllObjectsResolve = resolve;
+        });
+
+        let doneResolve: any;
+        const donePromise = new Promise((resolve) => {
+            doneResolve = resolve;
+        });
 
         await watch.watch(
             path,
@@ -236,35 +217,40 @@ describe('Watch', () => {
             (phase: string, obj: string) => {
                 receivedTypes.push(phase);
                 receivedObjects.push(obj);
+                if (receivedObjects.length === 1) {
+                    handledAllObjectsResolve();
+                }
             },
             (err: any) => {
-                doneCalled = true;
                 doneErr.push(err);
+                doneResolve();
             },
         );
 
-        verify(fakeRequestor.webRequest(anything()));
-
-        const [opts] = capture(fakeRequestor.webRequest).last();
-        const reqOpts: request.OptionsWithUri = opts as request.OptionsWithUri;
-
-        expect(reqOpts.uri).to.equal(`${server}${path}`);
-        expect(reqOpts.method).to.equal('GET');
-        expect(reqOpts.json).to.equal(true);
+        await handledAllObjectsPromise;
 
         expect(receivedTypes).to.deep.equal([obj1.type]);
         expect(receivedObjects).to.deep.equal([obj1.object]);
 
-        expect(doneCalled).to.equal(true);
+        expect(doneErr.length).to.equal(0);
+
+        const errIn = new Error('err');
+        (response as IncomingMessage).socket.destroy(errIn);
+
+        await donePromise;
+
         expect(doneErr.length).to.equal(1);
         expect(doneErr[0]).to.deep.equal(errIn);
+
+        s.done();
+
+        stream.destroy();
     });
 
-    it.skip('should handle server side close correctly', async () => {
+    it('should handle server side close correctly', async () => {
         const kc = new KubeConfig();
         Object.assign(kc, fakeConfig);
-        const fakeRequestor = mock(DefaultRequest);
-        const watch = new Watch(kc, instance(fakeRequestor));
+        const watch = new Watch(kc);
 
         const obj1 = {
             type: 'ADDED',
@@ -273,20 +259,35 @@ describe('Watch', () => {
             },
         };
 
-        const fakeRequest = new FakeRequest();
-        fakeRequest.pipe = function (stream) {
-            stream.write(JSON.stringify(obj1) + '\n');
-            stream.emit('close');
-        };
+        const stream = new PassThrough();
 
-        when(fakeRequestor.webRequest(anything())).thenReturn(fakeRequest);
+        const [scope] = systemUnderTest();
 
-        const path = '/some/path/to/object';
+        const path = '/some/path/to/object?watch=true';
+
+        let response: IncomingMessage | undefined;
+
+        const s = scope.get(path).reply(200, function (): PassThrough {
+            this.req.on('response', (r) => {
+                response = r;
+            });
+            stream.push(JSON.stringify(obj1) + '\n');
+            return stream;
+        });
 
         const receivedTypes: string[] = [];
         const receivedObjects: string[] = [];
-        let doneCalled = false;
-        let doneErr: any;
+        const doneErr: any[] = [];
+
+        let handledAllObjectsResolve: any;
+        const handledAllObjectsPromise = new Promise((resolve) => {
+            handledAllObjectsResolve = resolve;
+        });
+
+        let doneResolve: any;
+        const donePromise = new Promise((resolve) => {
+            doneResolve = resolve;
+        });
 
         await watch.watch(
             path,
@@ -294,34 +295,39 @@ describe('Watch', () => {
             (phase: string, obj: string) => {
                 receivedTypes.push(phase);
                 receivedObjects.push(obj);
+                if (receivedObjects.length === 1) {
+                    handledAllObjectsResolve();
+                }
             },
             (err: any) => {
-                doneCalled = true;
-                doneErr = err;
+                doneErr.push(err);
+                doneResolve();
             },
         );
 
-        verify(fakeRequestor.webRequest(anything()));
-
-        const [opts] = capture(fakeRequestor.webRequest).last();
-        const reqOpts: request.OptionsWithUri = opts as request.OptionsWithUri;
-
-        expect(reqOpts.uri).to.equal(`${server}${path}`);
-        expect(reqOpts.method).to.equal('GET');
-        expect(reqOpts.json).to.equal(true);
+        await handledAllObjectsPromise;
 
         expect(receivedTypes).to.deep.equal([obj1.type]);
         expect(receivedObjects).to.deep.equal([obj1.object]);
 
-        expect(doneCalled).to.equal(true);
-        expect(doneErr).to.be.null;
+        expect(doneErr.length).to.equal(0);
+
+        stream.end();
+
+        await donePromise;
+
+        expect(doneErr.length).to.equal(1);
+        expect(doneErr[0]).to.equal(null);
+
+        s.done();
+
+        stream.destroy();
     });
 
-    it.skip('should ignore JSON parse errors', async () => {
+    it('should ignore JSON parse errors', async () => {
         const kc = new KubeConfig();
         Object.assign(kc, fakeConfig);
-        const fakeRequestor = mock(DefaultRequest);
-        const watch = new Watch(kc, instance(fakeRequestor));
+        const watch = new Watch(kc);
 
         const obj = {
             type: 'MODIFIED',
@@ -330,19 +336,26 @@ describe('Watch', () => {
             },
         };
 
-        const fakeRequest = new FakeRequest();
-        fakeRequest.pipe = function (stream) {
-            stream.write(JSON.stringify(obj) + '\n');
-            stream.write('{"truncated json\n');
-        };
+        const stream = new PassThrough();
 
-        when(fakeRequestor.webRequest(anything())).thenReturn(fakeRequest);
+        const [scope] = systemUnderTest();
 
-        const path = '/some/path/to/object';
+        const path = '/some/path/to/object?watch=true';
+
+        const s = scope.get(path).reply(200, () => {
+            stream.push(JSON.stringify(obj) + '\n');
+            stream.write('{"truncated json\n');
+            return stream;
+        });
 
         const receivedTypes: string[] = [];
         const receivedObjects: string[] = [];
 
+        let doneResolve: any;
+        const donePromise = new Promise((resolve) => {
+            doneResolve = resolve;
+        });
+
         await watch.watch(
             path,
             {},
@@ -351,17 +364,18 @@ describe('Watch', () => {
                 receivedObjects.push(recievedObject);
             },
             () => {
-                // ignore
+                doneResolve();
             },
         );
 
-        verify(fakeRequestor.webRequest(anything()));
+        stream.end();
 
-        const [opts, doneCallback] = capture(fakeRequestor.webRequest).last();
-        const reqOpts: request.OptionsWithUri = opts as request.OptionsWithUri;
+        await donePromise;
 
         expect(receivedTypes).to.deep.equal([obj.type]);
         expect(receivedObjects).to.deep.equal([obj.object]);
+
+        s.done();
     });
 
     it('should throw on empty config', () => {
diff --git a/test/match-buffer.ts b/test/match-buffer.ts
index fd4e4e27..bc4c0a22 100644
--- a/test/match-buffer.ts
+++ b/test/match-buffer.ts
@@ -28,12 +28,7 @@ class StringBufferMatcher extends Matcher {
   }
 }
 
-export function assertRequestOptionsEqual(options1: RequestOptions, options2: RequestOptions): void {
-  //@ts-ignore agent has type Agent | Boolean which we expect to be populated with Agent here
-  const agent1: Agent = options1.agent
-  //@ts-ignore
-  const agent2: Agent = options2.agent
-
+export function assertRequestAgentsEqual(agent1: Agent, agent2: Agent): void {
   const BUFFER_EQUAL_TRUE = 0
   const ca1 = agent1.options.ca
   const ca2 = agent2.options.ca
@@ -55,10 +50,18 @@ export function assertRequestOptionsEqual(options1: RequestOptions, options2: Re
   if(key1 !== key2 && Buffer.compare(key1,key2) !== BUFFER_EQUAL_TRUE){
     throw("unequal agent key buffer")
   }
-  
+
   expect(agent1.options.passphrase).to.equal(agent2.options.passphrase);
   expect(agent1.options.pfx).to.equal(agent2.options.pfx);
   expect(agent1.options.rejectUnauthorized).to.equal(agent2.options.rejectUnauthorized);
+}
+
+export function assertRequestOptionsEqual(options1: RequestOptions, options2: RequestOptions): void {
+  //@ts-ignore agent has type Agent | Boolean which we expect to be populated with Agent here
+  const agent1: Agent = options1.agent
+  //@ts-ignore
+  const agent2: Agent = options2.agent
+  assertRequestAgentsEqual(agent1, agent2)
 
   expect(options1.auth).to.equal(options2.auth)
   expect(options1.headers).to.deep.equal(options2.headers)