diff --git a/.eslintrc.json b/.eslintrc.json
index 7c1365d6b12782f5f80c449f071272f516a550d1..0461b50ee770cc07e2ed473a18186fa5d700cf0f 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -36,6 +36,7 @@
                 "project": "./tsconfig.eslint.json"
             },
             "rules": {
+                "dot-notation": 0,
                 "@typescript-eslint/prefer-for-of": 0,
                 "@typescript-eslint/member-ordering": 0,
                 "@typescript-eslint/explicit-function-return-type": 0,
@@ -55,6 +56,7 @@
                 "@typescript-eslint/prefer-includes": 2,
                 "@typescript-eslint/no-unnecessary-condition": 2,
                 "@typescript-eslint/switch-exhaustiveness-check": 2,
+                "@typescript-eslint/no-duplicate-imports": 2,
                 "@typescript-eslint/prefer-nullish-coalescing": 2
             }
         }
diff --git a/README.md b/README.md
index 380e1dc7f70c8828e62387c5e94565af7c539834..2cde38c8ca9f12df988688678c52f6b618388d46 100644
--- a/README.md
+++ b/README.md
@@ -22,19 +22,21 @@ below.
 -   ๐Ÿงช Partial implementation of jQuery/Sizzle extensions (see
     [cheerio-select](https://github.com/cheeriojs/cheerio-select) for the
     remaining selectors)
--   ๐Ÿง‘โ€๐Ÿ”ฌ High test coverage, including the full test suites from Sizzle, Qwery
-    and NWMatcher.
+-   ๐Ÿง‘โ€๐Ÿ”ฌ High test coverage, including the full test suites from
+    [`Sizzle`](https://github.com/jquery/sizzle),
+    [`Qwery`](https://github.com/ded/qwery) and
+    [`NWMatcher`](https://github.com/dperini/nwmatcher/) and .
 -   ๐Ÿฅผ Reliably great performance
 
 ## Why?
 
 Most CSS engines written in JavaScript execute selectors left-to-right. That
-means thet execute every component of the selector in order, from left to right
-_(duh)_. As an example: For the selector `a b`, these engines will first query
-for `a` elements, then search these for `b` elements. (That's the approach of
-eg. [`Sizzle`](https://github.com/jquery/sizzle),
-[`nwmatcher`](https://github.com/dperini/nwmatcher/) and
-[`qwery`](https://github.com/ded/qwery).)
+means thet execute every component of the selector in order, from left to right.
+As an example: For the selector `a b`, these engines will first query for `a`
+elements, then search these for `b` elements. (That's the approach of eg.
+[`Sizzle`](https://github.com/jquery/sizzle),
+[`Qwery`](https://github.com/ded/qwery) and
+[`NWMatcher`](https://github.com/dperini/nwmatcher/).)
 
 While this works, it has some downsides: Children of `a`s will be checked
 multiple times; first, to check if they are also `a`s, then, for every superior
@@ -100,7 +102,7 @@ _//TODO: More in-depth description. Implementation details. Build a spaceship._
 const CSSselect = require("css-select");
 ```
 
-**Note:** css-select throws errors when invalid selectors are passed to it.This
+**Note:** css-select throws errors when invalid selectors are passed to it. This
 is done to aid with writing css selectors, but can be unexpected when processing
 arbitrary strings.
 
@@ -139,11 +141,18 @@ All options are optional.
 -   `adapter`: The adapter to use when interacting with the backing DOM
     structure. By default it uses the `domutils` module.
 -   `context`: The context of the current query. Used to limit the scope of
-    searches. Can be matched directly using the `:scope` pseudo-selector.
+    searches. Can be matched directly using the `:scope` pseudo-class.
+-   `relativeSelector`: By default, selectors are relative to the `context`,
+    which means that no parent elements of the context will be matched. (Eg.
+    `a b c` with context `b` will never give any results.) If `relativeSelector`
+    is set to `false`, selectors won't be
+    [absolutized](http://www.w3.org/TR/selectors4/#absolutizing) and selectors
+    can test for parent elements outside of the `context`.
 -   `cacheResults`: Allow css-select to cache results for some selectors,
     sometimes greatly improving querying performance. Disable this if your
     document can change in between queries with the same compiled selector.
     Default: `true`.
+-   `pseudos`: A map of pseudo-class names to functions or strings.
 
 #### Custom Adapters
 
diff --git a/package-lock.json b/package-lock.json
index e676ece32b977d0c0d95cb2b7caca8cbc9938af7..bbbf438e1c69845b66d117286a4f019b8f6e9abd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,34 +1,34 @@
 {
     "name": "css-select",
-    "version": "4.2.1",
+    "version": "5.1.0",
     "lockfileVersion": 2,
     "requires": true,
     "packages": {
         "": {
             "name": "css-select",
-            "version": "4.2.1",
+            "version": "5.1.0",
             "license": "BSD-2-Clause",
             "dependencies": {
                 "boolbase": "^1.0.0",
-                "css-what": "^5.1.0",
-                "domhandler": "^4.3.0",
-                "domutils": "^2.8.0",
+                "css-what": "^6.1.0",
+                "domhandler": "^5.0.2",
+                "domutils": "^3.0.1",
                 "nth-check": "^2.0.1"
             },
             "devDependencies": {
                 "@types/boolbase": "^1.0.1",
-                "@types/jest": "^27.0.3",
-                "@types/node": "^17.0.4",
-                "@typescript-eslint/eslint-plugin": "^5.8.0",
-                "@typescript-eslint/parser": "^5.8.0",
+                "@types/jest": "^27.4.1",
+                "@types/node": "^17.0.29",
+                "@typescript-eslint/eslint-plugin": "^5.21.0",
+                "@typescript-eslint/parser": "^5.21.0",
                 "cheerio-soupselect": "^0.1.1",
-                "eslint": "^8.5.0",
-                "eslint-config-prettier": "^8.1.0",
-                "htmlparser2": "^7.2.0",
-                "jest": "^27.4.5",
-                "prettier": "^2.5.1",
-                "ts-jest": "^27.1.2",
-                "typescript": "^4.5.4"
+                "eslint": "^8.14.0",
+                "eslint-config-prettier": "^8.5.0",
+                "htmlparser2": "^8.0.0",
+                "jest": "^27.5.1",
+                "prettier": "^2.6.2",
+                "ts-jest": "^27.1.4",
+                "typescript": "^4.6.3"
             },
             "funding": {
                 "url": "https://github.com/sponsors/fb55"
@@ -247,9 +247,9 @@
             }
         },
         "node_modules/@babel/helper-plugin-utils": {
-            "version": "7.16.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.5.tgz",
-            "integrity": "sha512-59KHWHXxVA9K4HNF4sbHCf+eJeFe0Te/ZFGqBT4OjXhrwvA04sGfaEGsVTdsjoszq0YTP49RC9UKe5g8uN2RwQ==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
+            "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==",
             "dev": true,
             "engines": {
                 "node": ">=6.9.0"
@@ -571,12 +571,12 @@
             }
         },
         "node_modules/@babel/plugin-syntax-typescript": {
-            "version": "7.16.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.5.tgz",
-            "integrity": "sha512-/d4//lZ1Vqb4mZ5xTep3dDK888j7BGM/iKqBmndBaoYAFPlPKrGU608VVBz5JeyAb6YQDjRu1UKqj86UhwWVgw==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz",
+            "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==",
             "dev": true,
             "dependencies": {
-                "@babel/helper-plugin-utils": "^7.16.5"
+                "@babel/helper-plugin-utils": "^7.16.7"
             },
             "engines": {
                 "node": ">=6.9.0"
@@ -648,16 +648,16 @@
             "dev": true
         },
         "node_modules/@eslint/eslintrc": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz",
-            "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==",
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz",
+            "integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==",
             "dev": true,
             "dependencies": {
                 "ajv": "^6.12.4",
                 "debug": "^4.3.2",
-                "espree": "^9.2.0",
+                "espree": "^9.3.1",
                 "globals": "^13.9.0",
-                "ignore": "^4.0.6",
+                "ignore": "^5.2.0",
                 "import-fresh": "^3.2.1",
                 "js-yaml": "^4.1.0",
                 "minimatch": "^3.0.4",
@@ -667,15 +667,6 @@
                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
             }
         },
-        "node_modules/@eslint/eslintrc/node_modules/ignore": {
-            "version": "4.0.6",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
-            "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
-            "dev": true,
-            "engines": {
-                "node": ">= 4"
-            }
-        },
         "node_modules/@humanwhocodes/config-array": {
             "version": "0.9.2",
             "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz",
@@ -753,16 +744,16 @@
             }
         },
         "node_modules/@jest/console": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.4.2.tgz",
-            "integrity": "sha512-xknHThRsPB/To1FUbi6pCe43y58qFC03zfb6R7fDb/FfC7k2R3i1l+izRBJf8DI46KhYGRaF14Eo9A3qbBoixg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz",
+            "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
-                "jest-message-util": "^27.4.2",
-                "jest-util": "^27.4.2",
+                "jest-message-util": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "slash": "^3.0.0"
             },
             "engines": {
@@ -770,35 +761,35 @@
             }
         },
         "node_modules/@jest/core": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.4.5.tgz",
-            "integrity": "sha512-3tm/Pevmi8bDsgvo73nX8p/WPng6KWlCyScW10FPEoN1HU4pwI83tJ3TsFvi1FfzsjwUlMNEPowgb/rPau/LTQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz",
+            "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==",
             "dev": true,
             "dependencies": {
-                "@jest/console": "^27.4.2",
-                "@jest/reporters": "^27.4.5",
-                "@jest/test-result": "^27.4.2",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/console": "^27.5.1",
+                "@jest/reporters": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "ansi-escapes": "^4.2.1",
                 "chalk": "^4.0.0",
                 "emittery": "^0.8.1",
                 "exit": "^0.1.2",
-                "graceful-fs": "^4.2.4",
-                "jest-changed-files": "^27.4.2",
-                "jest-config": "^27.4.5",
-                "jest-haste-map": "^27.4.5",
-                "jest-message-util": "^27.4.2",
-                "jest-regex-util": "^27.4.0",
-                "jest-resolve": "^27.4.5",
-                "jest-resolve-dependencies": "^27.4.5",
-                "jest-runner": "^27.4.5",
-                "jest-runtime": "^27.4.5",
-                "jest-snapshot": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
-                "jest-watcher": "^27.4.2",
+                "graceful-fs": "^4.2.9",
+                "jest-changed-files": "^27.5.1",
+                "jest-config": "^27.5.1",
+                "jest-haste-map": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-resolve-dependencies": "^27.5.1",
+                "jest-runner": "^27.5.1",
+                "jest-runtime": "^27.5.1",
+                "jest-snapshot": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-validate": "^27.5.1",
+                "jest-watcher": "^27.5.1",
                 "micromatch": "^4.0.4",
                 "rimraf": "^3.0.0",
                 "slash": "^3.0.0",
@@ -817,77 +808,77 @@
             }
         },
         "node_modules/@jest/environment": {
-            "version": "27.4.4",
-            "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.4.4.tgz",
-            "integrity": "sha512-q+niMx7cJgt/t/b6dzLOh4W8Ef/8VyKG7hxASK39jakijJzbFBGpptx3RXz13FFV7OishQ9lTbv+dQ5K3EhfDQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz",
+            "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==",
             "dev": true,
             "dependencies": {
-                "@jest/fake-timers": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/fake-timers": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
-                "jest-mock": "^27.4.2"
+                "jest-mock": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/@jest/fake-timers": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.4.2.tgz",
-            "integrity": "sha512-f/Xpzn5YQk5adtqBgvw1V6bF8Nx3hY0OIRRpCvWcfPl0EAjdqWPdhH3t/3XpiWZqtjIEHDyMKP9ajpva1l4Zmg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz",
+            "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@sinonjs/fake-timers": "^8.0.1",
                 "@types/node": "*",
-                "jest-message-util": "^27.4.2",
-                "jest-mock": "^27.4.2",
-                "jest-util": "^27.4.2"
+                "jest-message-util": "^27.5.1",
+                "jest-mock": "^27.5.1",
+                "jest-util": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/@jest/globals": {
-            "version": "27.4.4",
-            "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.4.4.tgz",
-            "integrity": "sha512-bqpqQhW30BOreXM8bA8t8JbOQzsq/WnPTnBl+It3UxAD9J8yxEAaBEylHx1dtBapAr/UBk8GidXbzmqnee8tYQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz",
+            "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==",
             "dev": true,
             "dependencies": {
-                "@jest/environment": "^27.4.4",
-                "@jest/types": "^27.4.2",
-                "expect": "^27.4.2"
+                "@jest/environment": "^27.5.1",
+                "@jest/types": "^27.5.1",
+                "expect": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/@jest/reporters": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.4.5.tgz",
-            "integrity": "sha512-3orsG4vi8zXuBqEoy2LbnC1kuvkg1KQUgqNxmxpQgIOQEPeV0onvZu+qDQnEoX8qTQErtqn/xzcnbpeTuOLSiA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz",
+            "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==",
             "dev": true,
             "dependencies": {
                 "@bcoe/v8-coverage": "^0.2.3",
-                "@jest/console": "^27.4.2",
-                "@jest/test-result": "^27.4.2",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/console": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "collect-v8-coverage": "^1.0.0",
                 "exit": "^0.1.2",
                 "glob": "^7.1.2",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "istanbul-lib-coverage": "^3.0.0",
-                "istanbul-lib-instrument": "^4.0.3",
+                "istanbul-lib-instrument": "^5.1.0",
                 "istanbul-lib-report": "^3.0.0",
                 "istanbul-lib-source-maps": "^4.0.0",
-                "istanbul-reports": "^3.0.2",
-                "jest-haste-map": "^27.4.5",
-                "jest-resolve": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-worker": "^27.4.5",
+                "istanbul-reports": "^3.1.3",
+                "jest-haste-map": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-worker": "^27.5.1",
                 "slash": "^3.0.0",
                 "source-map": "^0.6.0",
                 "string-length": "^4.0.1",
@@ -907,13 +898,13 @@
             }
         },
         "node_modules/@jest/source-map": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.4.0.tgz",
-            "integrity": "sha512-Ntjx9jzP26Bvhbm93z/AKcPRj/9wrkI88/gK60glXDx1q+IeI0rf7Lw2c89Ch6ofonB0On/iRDreQuQ6te9pgQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz",
+            "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==",
             "dev": true,
             "dependencies": {
                 "callsites": "^3.0.0",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "source-map": "^0.6.0"
             },
             "engines": {
@@ -921,13 +912,13 @@
             }
         },
         "node_modules/@jest/test-result": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.4.2.tgz",
-            "integrity": "sha512-kr+bCrra9jfTgxHXHa2UwoQjxvQk3Am6QbpAiJ5x/50LW8llOYrxILkqY0lZRW/hu8FXesnudbql263+EW9iNA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz",
+            "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==",
             "dev": true,
             "dependencies": {
-                "@jest/console": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/console": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/istanbul-lib-coverage": "^2.0.0",
                 "collect-v8-coverage": "^1.0.0"
             },
@@ -936,38 +927,38 @@
             }
         },
         "node_modules/@jest/test-sequencer": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.4.5.tgz",
-            "integrity": "sha512-n5woIn/1v+FT+9hniymHPARA9upYUmfi5Pw9ewVwXCDlK4F5/Gkees9v8vdjGdAIJ2MPHLHodiajLpZZanWzEQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz",
+            "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==",
             "dev": true,
             "dependencies": {
-                "@jest/test-result": "^27.4.2",
-                "graceful-fs": "^4.2.4",
-                "jest-haste-map": "^27.4.5",
-                "jest-runtime": "^27.4.5"
+                "@jest/test-result": "^27.5.1",
+                "graceful-fs": "^4.2.9",
+                "jest-haste-map": "^27.5.1",
+                "jest-runtime": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/@jest/transform": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.4.5.tgz",
-            "integrity": "sha512-PuMet2UlZtlGzwc6L+aZmR3I7CEBpqadO03pU40l2RNY2fFJ191b9/ITB44LNOhVtsyykx0OZvj0PCyuLm7Eew==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz",
+            "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==",
             "dev": true,
             "dependencies": {
                 "@babel/core": "^7.1.0",
-                "@jest/types": "^27.4.2",
-                "babel-plugin-istanbul": "^6.0.0",
+                "@jest/types": "^27.5.1",
+                "babel-plugin-istanbul": "^6.1.1",
                 "chalk": "^4.0.0",
                 "convert-source-map": "^1.4.0",
                 "fast-json-stable-stringify": "^2.0.0",
-                "graceful-fs": "^4.2.4",
-                "jest-haste-map": "^27.4.5",
-                "jest-regex-util": "^27.4.0",
-                "jest-util": "^27.4.2",
+                "graceful-fs": "^4.2.9",
+                "jest-haste-map": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "micromatch": "^4.0.4",
-                "pirates": "^4.0.1",
+                "pirates": "^4.0.4",
                 "slash": "^3.0.0",
                 "source-map": "^0.6.1",
                 "write-file-atomic": "^3.0.0"
@@ -977,9 +968,9 @@
             }
         },
         "node_modules/@jest/types": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.4.2.tgz",
-            "integrity": "sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz",
+            "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==",
             "dev": true,
             "dependencies": {
                 "@types/istanbul-lib-coverage": "^2.0.0",
@@ -1055,9 +1046,9 @@
             }
         },
         "node_modules/@types/babel__core": {
-            "version": "7.1.16",
-            "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz",
-            "integrity": "sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==",
+            "version": "7.1.18",
+            "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.18.tgz",
+            "integrity": "sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==",
             "dev": true,
             "dependencies": {
                 "@babel/parser": "^7.1.0",
@@ -1068,9 +1059,9 @@
             }
         },
         "node_modules/@types/babel__generator": {
-            "version": "7.6.3",
-            "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz",
-            "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==",
+            "version": "7.6.4",
+            "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
+            "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
             "dev": true,
             "dependencies": {
                 "@babel/types": "^7.0.0"
@@ -1135,31 +1126,31 @@
             }
         },
         "node_modules/@types/jest": {
-            "version": "27.0.3",
-            "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.3.tgz",
-            "integrity": "sha512-cmmwv9t7gBYt7hNKH5Spu7Kuu/DotGa+Ff+JGRKZ4db5eh8PnKS4LuebJ3YLUoyOyIHraTGyULn23YtEAm0VSg==",
+            "version": "27.4.1",
+            "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz",
+            "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==",
             "dev": true,
             "dependencies": {
-                "jest-diff": "^27.0.0",
+                "jest-matcher-utils": "^27.0.0",
                 "pretty-format": "^27.0.0"
             }
         },
         "node_modules/@types/json-schema": {
-            "version": "7.0.9",
-            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
-            "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
+            "version": "7.0.11",
+            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+            "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
             "dev": true
         },
         "node_modules/@types/node": {
-            "version": "17.0.4",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.4.tgz",
-            "integrity": "sha512-6xwbrW4JJiJLgF+zNypN5wr2ykM9/jHcL7rQ8fZe2vuftggjzZeRSM4OwRc6Xk8qWjwJ99qVHo/JgOGmomWRog==",
+            "version": "17.0.29",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.29.tgz",
+            "integrity": "sha512-tx5jMmMFwx7wBwq/V7OohKDVb/JwJU5qCVkeLMh1//xycAJ/ESuw9aJ9SEtlCZDYi2pBfe4JkisSoAtbOsBNAA==",
             "dev": true
         },
         "node_modules/@types/prettier": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.2.tgz",
-            "integrity": "sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA==",
+            "version": "2.4.3",
+            "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.3.tgz",
+            "integrity": "sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w==",
             "dev": true
         },
         "node_modules/@types/stack-utils": {
@@ -1184,13 +1175,14 @@
             "dev": true
         },
         "node_modules/@typescript-eslint/eslint-plugin": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.8.0.tgz",
-            "integrity": "sha512-spu1UW7QuBn0nJ6+psnfCc3iVoQAifjKORgBngKOmC8U/1tbe2YJMzYQqDGYB4JCss7L8+RM2kKLb1B1Aw9BNA==",
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.21.0.tgz",
+            "integrity": "sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg==",
             "dev": true,
             "dependencies": {
-                "@typescript-eslint/experimental-utils": "5.8.0",
-                "@typescript-eslint/scope-manager": "5.8.0",
+                "@typescript-eslint/scope-manager": "5.21.0",
+                "@typescript-eslint/type-utils": "5.21.0",
+                "@typescript-eslint/utils": "5.21.0",
                 "debug": "^4.3.2",
                 "functional-red-black-tree": "^1.0.1",
                 "ignore": "^5.1.8",
@@ -1215,18 +1207,16 @@
                 }
             }
         },
-        "node_modules/@typescript-eslint/experimental-utils": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.8.0.tgz",
-            "integrity": "sha512-KN5FvNH71bhZ8fKtL+lhW7bjm7cxs1nt+hrDZWIqb6ViCffQcWyLunGrgvISgkRojIDcXIsH+xlFfI4RCDA0xA==",
+        "node_modules/@typescript-eslint/parser": {
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.21.0.tgz",
+            "integrity": "sha512-8RUwTO77hstXUr3pZoWZbRQUxXcSXafZ8/5gpnQCfXvgmP9gpNlRGlWzvfbEQ14TLjmtU8eGnONkff8U2ui2Eg==",
             "dev": true,
             "dependencies": {
-                "@types/json-schema": "^7.0.9",
-                "@typescript-eslint/scope-manager": "5.8.0",
-                "@typescript-eslint/types": "5.8.0",
-                "@typescript-eslint/typescript-estree": "5.8.0",
-                "eslint-scope": "^5.1.1",
-                "eslint-utils": "^3.0.0"
+                "@typescript-eslint/scope-manager": "5.21.0",
+                "@typescript-eslint/types": "5.21.0",
+                "@typescript-eslint/typescript-estree": "5.21.0",
+                "debug": "^4.3.2"
             },
             "engines": {
                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1237,18 +1227,21 @@
             },
             "peerDependencies": {
                 "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+            },
+            "peerDependenciesMeta": {
+                "typescript": {
+                    "optional": true
+                }
             }
         },
-        "node_modules/@typescript-eslint/parser": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.8.0.tgz",
-            "integrity": "sha512-Gleacp/ZhRtJRYs5/T8KQR3pAQjQI89Dn/k+OzyCKOsLiZH2/Vh60cFBTnFsHNI6WAD+lNUo/xGZ4NeA5u0Ipw==",
+        "node_modules/@typescript-eslint/scope-manager": {
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.21.0.tgz",
+            "integrity": "sha512-XTX0g0IhvzcH/e3393SvjRCfYQxgxtYzL3UREteUneo72EFlt7UNoiYnikUtmGVobTbhUDByhJ4xRBNe+34kOQ==",
             "dev": true,
             "dependencies": {
-                "@typescript-eslint/scope-manager": "5.8.0",
-                "@typescript-eslint/types": "5.8.0",
-                "@typescript-eslint/typescript-estree": "5.8.0",
-                "debug": "^4.3.2"
+                "@typescript-eslint/types": "5.21.0",
+                "@typescript-eslint/visitor-keys": "5.21.0"
             },
             "engines": {
                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1256,24 +1249,17 @@
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
             }
         },
-        "node_modules/@typescript-eslint/scope-manager": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.8.0.tgz",
-            "integrity": "sha512-x82CYJsLOjPCDuFFEbS6e7K1QEWj7u5Wk1alw8A+gnJiYwNnDJk0ib6PCegbaPMjrfBvFKa7SxE3EOnnIQz2Gg==",
+        "node_modules/@typescript-eslint/type-utils": {
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.21.0.tgz",
+            "integrity": "sha512-MxmLZj0tkGlkcZCSE17ORaHl8Th3JQwBzyXL/uvC6sNmu128LsgjTX0NIzy+wdH2J7Pd02GN8FaoudJntFvSOw==",
             "dev": true,
             "dependencies": {
-                "@typescript-eslint/types": "5.8.0",
-                "@typescript-eslint/visitor-keys": "5.8.0"
+                "@typescript-eslint/utils": "5.21.0",
+                "debug": "^4.3.2",
+                "tsutils": "^3.21.0"
             },
             "engines": {
                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1281,12 +1267,20 @@
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "eslint": "*"
+            },
+            "peerDependenciesMeta": {
+                "typescript": {
+                    "optional": true
+                }
             }
         },
         "node_modules/@typescript-eslint/types": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.8.0.tgz",
-            "integrity": "sha512-LdCYOqeqZWqCMOmwFnum6YfW9F3nKuxJiR84CdIRN5nfHJ7gyvGpXWqL/AaW0k3Po0+wm93ARAsOdzlZDPCcXg==",
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.21.0.tgz",
+            "integrity": "sha512-XnOOo5Wc2cBlq8Lh5WNvAgHzpjnEzxn4CJBwGkcau7b/tZ556qrWXQz4DJyChYg8JZAD06kczrdgFPpEQZfDsA==",
             "dev": true,
             "engines": {
                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1297,13 +1291,13 @@
             }
         },
         "node_modules/@typescript-eslint/typescript-estree": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.8.0.tgz",
-            "integrity": "sha512-srfeZ3URdEcUsSLbkOFqS7WoxOqn8JNil2NSLO9O+I2/Uyc85+UlfpEvQHIpj5dVts7KKOZnftoJD/Fdv0L7nQ==",
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.21.0.tgz",
+            "integrity": "sha512-Y8Y2T2FNvm08qlcoSMoNchh9y2Uj3QmjtwNMdRQkcFG7Muz//wfJBGBxh8R7HAGQFpgYpdHqUpEoPQk+q9Kjfg==",
             "dev": true,
             "dependencies": {
-                "@typescript-eslint/types": "5.8.0",
-                "@typescript-eslint/visitor-keys": "5.8.0",
+                "@typescript-eslint/types": "5.21.0",
+                "@typescript-eslint/visitor-keys": "5.21.0",
                 "debug": "^4.3.2",
                 "globby": "^11.0.4",
                 "is-glob": "^4.0.3",
@@ -1323,13 +1317,37 @@
                 }
             }
         },
+        "node_modules/@typescript-eslint/utils": {
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.21.0.tgz",
+            "integrity": "sha512-q/emogbND9wry7zxy7VYri+7ydawo2HDZhRZ5k6yggIvXa7PvBbAAZ4PFH/oZLem72ezC4Pr63rJvDK/sTlL8Q==",
+            "dev": true,
+            "dependencies": {
+                "@types/json-schema": "^7.0.9",
+                "@typescript-eslint/scope-manager": "5.21.0",
+                "@typescript-eslint/types": "5.21.0",
+                "@typescript-eslint/typescript-estree": "5.21.0",
+                "eslint-scope": "^5.1.1",
+                "eslint-utils": "^3.0.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+            }
+        },
         "node_modules/@typescript-eslint/visitor-keys": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.8.0.tgz",
-            "integrity": "sha512-+HDIGOEMnqbxdAHegxvnOqESUH6RWFRR2b8qxP1W9CZnnYh4Usz6MBL+2KMAgPk/P0o9c1HqnYtwzVH6GTIqug==",
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz",
+            "integrity": "sha512-SX8jNN+iHqAF0riZQMkm7e8+POXa/fXw5cxL+gjpyP+FI+JVNhii53EmQgDAfDcBpFekYSlO0fGytMQwRiMQCA==",
             "dev": true,
             "dependencies": {
-                "@typescript-eslint/types": "5.8.0",
+                "@typescript-eslint/types": "5.21.0",
                 "eslint-visitor-keys": "^3.0.0"
             },
             "engines": {
@@ -1347,9 +1365,9 @@
             "dev": true
         },
         "node_modules/acorn": {
-            "version": "8.6.0",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz",
-            "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==",
+            "version": "8.7.0",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
+            "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
             "dev": true,
             "bin": {
                 "acorn": "bin/acorn"
@@ -1426,15 +1444,6 @@
                 "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",
-            "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
         "node_modules/ansi-escapes": {
             "version": "4.3.2",
             "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
@@ -1521,18 +1530,18 @@
             "dev": true
         },
         "node_modules/babel-jest": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.4.5.tgz",
-            "integrity": "sha512-3uuUTjXbgtODmSv/DXO9nZfD52IyC2OYTFaXGRzL0kpykzroaquCrD5+lZNafTvZlnNqZHt5pb0M08qVBZnsnA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz",
+            "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==",
             "dev": true,
             "dependencies": {
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/babel__core": "^7.1.14",
-                "babel-plugin-istanbul": "^6.0.0",
-                "babel-preset-jest": "^27.4.0",
+                "babel-plugin-istanbul": "^6.1.1",
+                "babel-preset-jest": "^27.5.1",
                 "chalk": "^4.0.0",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "slash": "^3.0.0"
             },
             "engines": {
@@ -1543,15 +1552,15 @@
             }
         },
         "node_modules/babel-plugin-istanbul": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz",
-            "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==",
+            "version": "6.1.1",
+            "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+            "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
             "dev": true,
             "dependencies": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@istanbuljs/load-nyc-config": "^1.0.0",
                 "@istanbuljs/schema": "^0.1.2",
-                "istanbul-lib-instrument": "^4.0.0",
+                "istanbul-lib-instrument": "^5.0.4",
                 "test-exclude": "^6.0.0"
             },
             "engines": {
@@ -1559,9 +1568,9 @@
             }
         },
         "node_modules/babel-plugin-jest-hoist": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.4.0.tgz",
-            "integrity": "sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz",
+            "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==",
             "dev": true,
             "dependencies": {
                 "@babel/template": "^7.3.3",
@@ -1597,12 +1606,12 @@
             }
         },
         "node_modules/babel-preset-jest": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz",
-            "integrity": "sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz",
+            "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==",
             "dev": true,
             "dependencies": {
-                "babel-plugin-jest-hoist": "^27.4.0",
+                "babel-plugin-jest-hoist": "^27.5.1",
                 "babel-preset-current-node-syntax": "^1.0.0"
             },
             "engines": {
@@ -1900,9 +1909,9 @@
             }
         },
         "node_modules/css-what": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
-            "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==",
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+            "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
             "engines": {
                 "node": ">= 6"
             },
@@ -2011,9 +2020,9 @@
             }
         },
         "node_modules/diff-sequences": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.4.0.tgz",
-            "integrity": "sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz",
+            "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==",
             "dev": true,
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
@@ -2044,22 +2053,22 @@
             }
         },
         "node_modules/dom-serializer": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-            "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+            "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
             "dependencies": {
-                "domelementtype": "^2.0.1",
-                "domhandler": "^4.2.0",
-                "entities": "^2.0.0"
+                "domelementtype": "^2.3.0",
+                "domhandler": "^5.0.2",
+                "entities": "^4.2.0"
             },
             "funding": {
                 "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
             }
         },
         "node_modules/domelementtype": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-            "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+            "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
             "funding": [
                 {
                     "type": "github",
@@ -2089,11 +2098,11 @@
             }
         },
         "node_modules/domhandler": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-            "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
+            "version": "5.0.2",
+            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.2.tgz",
+            "integrity": "sha512-pr8ToPIuwBonzUy42STpc5Cf0m69zsQ7gtCLLvKrTbhVRnRohT2pLiJmGp3PAh16nDVWpYpcRpdjuk1vFmnQUg==",
             "dependencies": {
-                "domelementtype": "^2.2.0"
+                "domelementtype": "^2.3.0"
             },
             "engines": {
                 "node": ">= 4"
@@ -2103,13 +2112,13 @@
             }
         },
         "node_modules/domutils": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
-            "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
+            "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
             "dependencies": {
-                "dom-serializer": "^1.0.1",
-                "domelementtype": "^2.2.0",
-                "domhandler": "^4.2.0"
+                "dom-serializer": "^2.0.0",
+                "domelementtype": "^2.3.0",
+                "domhandler": "^5.0.1"
             },
             "funding": {
                 "url": "https://github.com/fb55/domutils?sponsor=1"
@@ -2139,294 +2148,25 @@
             "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
             "dev": true
         },
-        "node_modules/enquirer": {
-            "version": "2.3.6",
-            "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
-            "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
-            "dev": true,
-            "dependencies": {
-                "ansi-colors": "^4.1.1"
-            },
-            "engines": {
-                "node": ">=8.6"
-            }
-        },
         "node_modules/entities": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-            "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz",
+            "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==",
+            "engines": {
+                "node": ">=0.12"
+            },
             "funding": {
                 "url": "https://github.com/fb55/entities?sponsor=1"
             }
         },
-        "node_modules/esbuild": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.2.tgz",
-            "integrity": "sha512-l076A6o/PIgcyM24s0dWmDI/b8RQf41uWoJu9I0M71CtW/YSw5T5NUeXxs5lo2tFQD+O4CW4nBHJXx3OY5NpXg==",
-            "dev": true,
-            "hasInstallScript": true,
-            "optional": true,
-            "peer": true,
-            "bin": {
-                "esbuild": "bin/esbuild"
-            },
-            "optionalDependencies": {
-                "esbuild-android-arm64": "0.14.2",
-                "esbuild-darwin-64": "0.14.2",
-                "esbuild-darwin-arm64": "0.14.2",
-                "esbuild-freebsd-64": "0.14.2",
-                "esbuild-freebsd-arm64": "0.14.2",
-                "esbuild-linux-32": "0.14.2",
-                "esbuild-linux-64": "0.14.2",
-                "esbuild-linux-arm": "0.14.2",
-                "esbuild-linux-arm64": "0.14.2",
-                "esbuild-linux-mips64le": "0.14.2",
-                "esbuild-linux-ppc64le": "0.14.2",
-                "esbuild-netbsd-64": "0.14.2",
-                "esbuild-openbsd-64": "0.14.2",
-                "esbuild-sunos-64": "0.14.2",
-                "esbuild-windows-32": "0.14.2",
-                "esbuild-windows-64": "0.14.2",
-                "esbuild-windows-arm64": "0.14.2"
-            }
-        },
-        "node_modules/esbuild-android-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.2.tgz",
-            "integrity": "sha512-hEixaKMN3XXCkoe+0WcexO4CcBVU5DCSUT+7P8JZiWZCbAjSkc9b6Yz2X5DSfQmRCtI/cQRU6TfMYrMQ5NBfdw==",
-            "cpu": [
-                "arm64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "android"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-darwin-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.2.tgz",
-            "integrity": "sha512-Uq8t0cbJQkxkQdbUfOl2wZqZ/AtLZjvJulR1HHnc96UgyzG9YlCLSDMiqjM+NANEy7/zzvwKJsy3iNC9wwqLJA==",
-            "cpu": [
-                "x64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "darwin"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-darwin-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.2.tgz",
-            "integrity": "sha512-619MSa17sr7YCIrUj88KzQu2ESA4jKYtIYfLU/smX6qNgxQt3Y/gzM4s6sgJ4fPQzirvmXgcHv1ZNQAs/Xh48A==",
-            "cpu": [
-                "arm64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "darwin"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-freebsd-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.2.tgz",
-            "integrity": "sha512-aP6FE/ZsChZpUV6F3HE3x1Pz0paoYXycJ7oLt06g0G9dhJKknPawXCqQg/WMyD+ldCEZfo7F1kavenPdIT/SGQ==",
-            "cpu": [
-                "x64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "freebsd"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-freebsd-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.2.tgz",
-            "integrity": "sha512-LSm98WTb1QIhyS83+Po0KTpZNdd2XpVpI9ua5rLWqKWbKeNRFwOsjeiuwBaRNc+O32s9oC2ZMefETxHBV6VNkQ==",
-            "cpu": [
-                "arm64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "freebsd"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-linux-32": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.2.tgz",
-            "integrity": "sha512-8VxnNEyeUbiGflTKcuVc5JEPTqXfsx2O6ABwUbfS1Hp26lYPRPC7pKQK5Dxa0MBejGc50jy7YZae3EGQUQ8EkQ==",
-            "cpu": [
-                "ia32"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "linux"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-linux-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.2.tgz",
-            "integrity": "sha512-4bzMS2dNxOJoFIiHId4w+tqQzdnsch71JJV1qZnbnErSFWcR9lRgpSqWnTTFtv6XM+MvltRzSXC5wQ7AEBY6Hg==",
-            "cpu": [
-                "x64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "linux"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-linux-arm": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.2.tgz",
-            "integrity": "sha512-PaylahvMHhH8YMfJPMKEqi64qA0Su+d4FNfHKvlKes/2dUe4QxgbwXT9oLVgy8iJdcFMrO7By4R8fS8S0p8aVQ==",
-            "cpu": [
-                "arm"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "linux"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-linux-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.2.tgz",
-            "integrity": "sha512-RlIVp0RwJrdtasDF1vTFueLYZ8WuFzxoQ1OoRFZOTyJHCGCNgh7xJIC34gd7B7+RT0CzLBB4LcM5n0LS+hIoww==",
-            "cpu": [
-                "arm64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "linux"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-linux-mips64le": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.2.tgz",
-            "integrity": "sha512-Fdwrq2roFnO5oetIiUQQueZ3+5soCxBSJswg3MvYaXDomj47BN6oAWMZgLrFh1oVrtWrxSDLCJBenYdbm2s+qQ==",
-            "cpu": [
-                "mips64el"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "linux"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-linux-ppc64le": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.2.tgz",
-            "integrity": "sha512-vxptskw8JfCDD9QqpRO0XnsM1osuWeRjPaXX1TwdveLogYsbdFtcuiuK/4FxGiNMUr1ojtnCS2rMPbY8puc5NA==",
-            "cpu": [
-                "ppc64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "linux"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-netbsd-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.2.tgz",
-            "integrity": "sha512-I8+LzYK5iSNpspS9eCV9sW67Rj8FgMHimGri4mKiGAmN0pNfx+hFX146rYtzGtewuxKtTsPywWteHx+hPRLDsw==",
-            "cpu": [
-                "x64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "netbsd"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-openbsd-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.2.tgz",
-            "integrity": "sha512-120HgMe9elidWUvM2E6mMf0csrGwx8sYDqUIJugyMy1oHm+/nT08bTAVXuwYG/rkMIqsEO9AlMxuYnwR6En/3Q==",
-            "cpu": [
-                "x64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "openbsd"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-sunos-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.2.tgz",
-            "integrity": "sha512-Q3xcf9Uyfra9UuCFxoLixVvdigo0daZaKJ97TL2KNA4bxRUPK18wwGUk3AxvgDQZpRmg82w9PnkaNYo7a+24ow==",
-            "cpu": [
-                "x64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "sunos"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-windows-32": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.2.tgz",
-            "integrity": "sha512-TW7O49tPsrq+N1sW8mb3m24j/iDGa4xzAZH4wHWwoIzgtZAYPKC0hpIhufRRG/LA30bdMChO9pjJZ5mtcybtBQ==",
-            "cpu": [
-                "ia32"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "win32"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-windows-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.2.tgz",
-            "integrity": "sha512-Rym6ViMNmi1E2QuQMWy0AFAfdY0wGwZD73BnzlsQBX5hZBuy/L+Speh7ucUZ16gwsrMM9v86icZUDrSN/lNBKg==",
-            "cpu": [
-                "x64"
-            ],
-            "dev": true,
-            "optional": true,
-            "os": [
-                "win32"
-            ],
-            "peer": true
-        },
-        "node_modules/esbuild-windows-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.2.tgz",
-            "integrity": "sha512-ZrLbhr0vX5Em/P1faMnHucjVVWPS+m3tktAtz93WkMZLmbRJevhiW1y4CbulBd2z0MEdXZ6emDa1zFHq5O5bSA==",
-            "cpu": [
-                "arm64"
-            ],
+        "node_modules/error-ex": {
+            "version": "1.3.2",
+            "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+            "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
             "dev": true,
-            "optional": true,
-            "os": [
-                "win32"
-            ],
-            "peer": true
+            "dependencies": {
+                "is-arrayish": "^0.2.1"
+            }
         },
         "node_modules/escalade": {
             "version": "3.1.1",
@@ -2532,24 +2272,23 @@
             }
         },
         "node_modules/eslint": {
-            "version": "8.5.0",
-            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz",
-            "integrity": "sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg==",
+            "version": "8.14.0",
+            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz",
+            "integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==",
             "dev": true,
             "dependencies": {
-                "@eslint/eslintrc": "^1.0.5",
+                "@eslint/eslintrc": "^1.2.2",
                 "@humanwhocodes/config-array": "^0.9.2",
                 "ajv": "^6.10.0",
                 "chalk": "^4.0.0",
                 "cross-spawn": "^7.0.2",
                 "debug": "^4.3.2",
                 "doctrine": "^3.0.0",
-                "enquirer": "^2.3.5",
                 "escape-string-regexp": "^4.0.0",
-                "eslint-scope": "^7.1.0",
+                "eslint-scope": "^7.1.1",
                 "eslint-utils": "^3.0.0",
-                "eslint-visitor-keys": "^3.1.0",
-                "espree": "^9.2.0",
+                "eslint-visitor-keys": "^3.3.0",
+                "espree": "^9.3.1",
                 "esquery": "^1.4.0",
                 "esutils": "^2.0.2",
                 "fast-deep-equal": "^3.1.3",
@@ -2557,7 +2296,7 @@
                 "functional-red-black-tree": "^1.0.1",
                 "glob-parent": "^6.0.1",
                 "globals": "^13.6.0",
-                "ignore": "^4.0.6",
+                "ignore": "^5.2.0",
                 "import-fresh": "^3.0.0",
                 "imurmurhash": "^0.1.4",
                 "is-glob": "^4.0.0",
@@ -2568,9 +2307,7 @@
                 "minimatch": "^3.0.4",
                 "natural-compare": "^1.4.0",
                 "optionator": "^0.9.1",
-                "progress": "^2.0.0",
                 "regexpp": "^3.2.0",
-                "semver": "^7.2.1",
                 "strip-ansi": "^6.0.1",
                 "strip-json-comments": "^3.1.0",
                 "text-table": "^0.2.0",
@@ -2587,9 +2324,9 @@
             }
         },
         "node_modules/eslint-config-prettier": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz",
-            "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==",
+            "version": "8.5.0",
+            "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
+            "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
             "dev": true,
             "bin": {
                 "eslint-config-prettier": "bin/cli.js"
@@ -2639,18 +2376,18 @@
             }
         },
         "node_modules/eslint-visitor-keys": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
-            "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==",
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+            "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
             "dev": true,
             "engines": {
                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
             }
         },
         "node_modules/eslint/node_modules/eslint-scope": {
-            "version": "7.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz",
-            "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==",
+            "version": "7.1.1",
+            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+            "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
             "dev": true,
             "dependencies": {
                 "esrecurse": "^4.3.0",
@@ -2669,24 +2406,15 @@
                 "node": ">=4.0"
             }
         },
-        "node_modules/eslint/node_modules/ignore": {
-            "version": "4.0.6",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
-            "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
-            "dev": true,
-            "engines": {
-                "node": ">= 4"
-            }
-        },
         "node_modules/espree": {
-            "version": "9.2.0",
-            "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz",
-            "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==",
+            "version": "9.3.1",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
+            "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
             "dev": true,
             "dependencies": {
-                "acorn": "^8.6.0",
+                "acorn": "^8.7.0",
                 "acorn-jsx": "^5.3.1",
-                "eslint-visitor-keys": "^3.1.0"
+                "eslint-visitor-keys": "^3.3.0"
             },
             "engines": {
                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2798,34 +2526,20 @@
             }
         },
         "node_modules/expect": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/expect/-/expect-27.4.2.tgz",
-            "integrity": "sha512-BjAXIDC6ZOW+WBFNg96J22D27Nq5ohn+oGcuP2rtOtcjuxNoV9McpQ60PcQWhdFOSBIQdR72e+4HdnbZTFSTyg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz",
+            "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
-                "ansi-styles": "^5.0.0",
-                "jest-get-type": "^27.4.0",
-                "jest-matcher-utils": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-regex-util": "^27.4.0"
+                "@jest/types": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "jest-matcher-utils": "^27.5.1",
+                "jest-message-util": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
-        "node_modules/expect/node_modules/ansi-styles": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
-            "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-            }
-        },
         "node_modules/fast-deep-equal": {
             "version": "3.1.3",
             "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -3064,9 +2778,9 @@
             }
         },
         "node_modules/globals": {
-            "version": "13.12.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
-            "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
+            "version": "13.13.0",
+            "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
+            "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
             "dev": true,
             "dependencies": {
                 "type-fest": "^0.20.2"
@@ -3099,9 +2813,9 @@
             }
         },
         "node_modules/graceful-fs": {
-            "version": "4.2.8",
-            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
-            "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
+            "version": "4.2.9",
+            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
+            "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
             "dev": true
         },
         "node_modules/has": {
@@ -3144,9 +2858,9 @@
             "dev": true
         },
         "node_modules/htmlparser2": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz",
-            "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==",
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.0.tgz",
+            "integrity": "sha512-4wbT2/t9kITgTLhFoPPzIh4xW/fDXE4NKQDcBhWC0fPCraSA5K26W8D09K5NAqNqsBp/f7wDN2LR2rA4GhlGhA==",
             "dev": true,
             "funding": [
                 "https://github.com/fb55/htmlparser2?sponsor=1",
@@ -3156,22 +2870,10 @@
                 }
             ],
             "dependencies": {
-                "domelementtype": "^2.0.1",
-                "domhandler": "^4.2.2",
-                "domutils": "^2.8.0",
-                "entities": "^3.0.1"
-            }
-        },
-        "node_modules/htmlparser2/node_modules/entities": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
-            "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.12"
-            },
-            "funding": {
-                "url": "https://github.com/fb55/entities?sponsor=1"
+                "domelementtype": "^2.3.0",
+                "domhandler": "^5.0.2",
+                "domutils": "^3.0.1",
+                "entities": "^4.3.0"
             }
         },
         "node_modules/http-proxy-agent": {
@@ -3223,9 +2925,9 @@
             }
         },
         "node_modules/ignore": {
-            "version": "5.1.8",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
-            "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+            "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
             "dev": true,
             "engines": {
                 "node": ">= 4"
@@ -3248,9 +2950,9 @@
             }
         },
         "node_modules/import-local": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz",
-            "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==",
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+            "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
             "dev": true,
             "dependencies": {
                 "pkg-dir": "^4.2.0",
@@ -3261,6 +2963,9 @@
             },
             "engines": {
                 "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/imurmurhash": {
@@ -3288,10 +2993,16 @@
             "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
             "dev": true
         },
+        "node_modules/is-arrayish": {
+            "version": "0.2.1",
+            "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+            "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+            "dev": true
+        },
         "node_modules/is-core-module": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
-            "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==",
+            "version": "2.8.1",
+            "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
+            "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
             "dev": true,
             "dependencies": {
                 "has": "^1.0.3"
@@ -3379,23 +3090,24 @@
             "dev": true
         },
         "node_modules/istanbul-lib-coverage": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.2.tgz",
-            "integrity": "sha512-o5+eTUYzCJ11/+JhW5/FUCdfsdoYVdQ/8I/OveE2XsjehYn5DdeSnNQAbjYaO8gQ6hvGTN6GM6ddQqpTVG5j8g==",
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
+            "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
             "dev": true,
             "engines": {
                 "node": ">=8"
             }
         },
         "node_modules/istanbul-lib-instrument": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
-            "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz",
+            "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==",
             "dev": true,
             "dependencies": {
-                "@babel/core": "^7.7.5",
+                "@babel/core": "^7.12.3",
+                "@babel/parser": "^7.14.7",
                 "@istanbuljs/schema": "^0.1.2",
-                "istanbul-lib-coverage": "^3.0.0",
+                "istanbul-lib-coverage": "^3.2.0",
                 "semver": "^6.3.0"
             },
             "engines": {
@@ -3440,9 +3152,9 @@
             }
         },
         "node_modules/istanbul-reports": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.1.tgz",
-            "integrity": "sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw==",
+            "version": "3.1.4",
+            "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz",
+            "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==",
             "dev": true,
             "dependencies": {
                 "html-escaper": "^2.0.0",
@@ -3453,14 +3165,14 @@
             }
         },
         "node_modules/jest": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest/-/jest-27.4.5.tgz",
-            "integrity": "sha512-uT5MiVN3Jppt314kidCk47MYIRilJjA/l2mxwiuzzxGUeJIvA8/pDaJOAX5KWvjAo7SCydcW0/4WEtgbLMiJkg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
+            "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==",
             "dev": true,
             "dependencies": {
-                "@jest/core": "^27.4.5",
+                "@jest/core": "^27.5.1",
                 "import-local": "^3.0.2",
-                "jest-cli": "^27.4.5"
+                "jest-cli": "^27.5.1"
             },
             "bin": {
                 "jest": "bin/jest.js"
@@ -3478,12 +3190,12 @@
             }
         },
         "node_modules/jest-changed-files": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.4.2.tgz",
-            "integrity": "sha512-/9x8MjekuzUQoPjDHbBiXbNEBauhrPU2ct7m8TfCg69ywt1y/N+yYwGh3gCpnqUS3klYWDU/lSNgv+JhoD2k1A==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz",
+            "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "execa": "^5.0.0",
                 "throat": "^6.0.1"
             },
@@ -3492,27 +3204,27 @@
             }
         },
         "node_modules/jest-circus": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.4.5.tgz",
-            "integrity": "sha512-eTNWa9wsvBwPykhMMShheafbwyakcdHZaEYh5iRrQ0PFJxkDP/e3U/FvzGuKWu2WpwUA3C3hPlfpuzvOdTVqnw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz",
+            "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==",
             "dev": true,
             "dependencies": {
-                "@jest/environment": "^27.4.4",
-                "@jest/test-result": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/environment": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "co": "^4.6.0",
                 "dedent": "^0.7.0",
-                "expect": "^27.4.2",
+                "expect": "^27.5.1",
                 "is-generator-fn": "^2.0.0",
-                "jest-each": "^27.4.2",
-                "jest-matcher-utils": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-runtime": "^27.4.5",
-                "jest-snapshot": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "pretty-format": "^27.4.2",
+                "jest-each": "^27.5.1",
+                "jest-matcher-utils": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-runtime": "^27.5.1",
+                "jest-snapshot": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "pretty-format": "^27.5.1",
                 "slash": "^3.0.0",
                 "stack-utils": "^2.0.3",
                 "throat": "^6.0.1"
@@ -3522,21 +3234,21 @@
             }
         },
         "node_modules/jest-cli": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.4.5.tgz",
-            "integrity": "sha512-hrky3DSgE0u7sQxaCL7bdebEPHx5QzYmrGuUjaPLmPE8jx5adtvGuOlRspvMoVLTTDOHRnZDoRLYJuA+VCI7Hg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz",
+            "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==",
             "dev": true,
             "dependencies": {
-                "@jest/core": "^27.4.5",
-                "@jest/test-result": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/core": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "chalk": "^4.0.0",
                 "exit": "^0.1.2",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "import-local": "^3.0.2",
-                "jest-config": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
+                "jest-config": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-validate": "^27.5.1",
                 "prompts": "^2.0.1",
                 "yargs": "^16.2.0"
             },
@@ -3556,33 +3268,35 @@
             }
         },
         "node_modules/jest-config": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.4.5.tgz",
-            "integrity": "sha512-t+STVJtPt+fpqQ8GBw850NtSQbnDOw/UzdPfzDaHQ48/AylQlW7LHj3dH+ndxhC1UxJ0Q3qkq7IH+nM1skwTwA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz",
+            "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==",
             "dev": true,
             "dependencies": {
-                "@babel/core": "^7.1.0",
-                "@jest/test-sequencer": "^27.4.5",
-                "@jest/types": "^27.4.2",
-                "babel-jest": "^27.4.5",
+                "@babel/core": "^7.8.0",
+                "@jest/test-sequencer": "^27.5.1",
+                "@jest/types": "^27.5.1",
+                "babel-jest": "^27.5.1",
                 "chalk": "^4.0.0",
                 "ci-info": "^3.2.0",
                 "deepmerge": "^4.2.2",
                 "glob": "^7.1.1",
-                "graceful-fs": "^4.2.4",
-                "jest-circus": "^27.4.5",
-                "jest-environment-jsdom": "^27.4.4",
-                "jest-environment-node": "^27.4.4",
-                "jest-get-type": "^27.4.0",
-                "jest-jasmine2": "^27.4.5",
-                "jest-regex-util": "^27.4.0",
-                "jest-resolve": "^27.4.5",
-                "jest-runner": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
+                "graceful-fs": "^4.2.9",
+                "jest-circus": "^27.5.1",
+                "jest-environment-jsdom": "^27.5.1",
+                "jest-environment-node": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "jest-jasmine2": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-runner": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-validate": "^27.5.1",
                 "micromatch": "^4.0.4",
-                "pretty-format": "^27.4.2",
-                "slash": "^3.0.0"
+                "parse-json": "^5.2.0",
+                "pretty-format": "^27.5.1",
+                "slash": "^3.0.0",
+                "strip-json-comments": "^3.1.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
@@ -3597,24 +3311,24 @@
             }
         },
         "node_modules/jest-diff": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.4.2.tgz",
-            "integrity": "sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz",
+            "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==",
             "dev": true,
             "dependencies": {
                 "chalk": "^4.0.0",
-                "diff-sequences": "^27.4.0",
-                "jest-get-type": "^27.4.0",
-                "pretty-format": "^27.4.2"
+                "diff-sequences": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "pretty-format": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-docblock": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.4.0.tgz",
-            "integrity": "sha512-7TBazUdCKGV7svZ+gh7C8esAnweJoG+SvcF6Cjqj4l17zA2q1cMwx2JObSioubk317H+cjcHgP+7fTs60paulg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz",
+            "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==",
             "dev": true,
             "dependencies": {
                 "detect-newline": "^3.0.0"
@@ -3624,33 +3338,33 @@
             }
         },
         "node_modules/jest-each": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.4.2.tgz",
-            "integrity": "sha512-53V2MNyW28CTruB3lXaHNk6PkiIFuzdOC9gR3C6j8YE/ACfrPnz+slB0s17AgU1TtxNzLuHyvNlLJ+8QYw9nBg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz",
+            "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "chalk": "^4.0.0",
-                "jest-get-type": "^27.4.0",
-                "jest-util": "^27.4.2",
-                "pretty-format": "^27.4.2"
+                "jest-get-type": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "pretty-format": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-environment-jsdom": {
-            "version": "27.4.4",
-            "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.4.4.tgz",
-            "integrity": "sha512-cYR3ndNfHBqQgFvS1RL7dNqSvD//K56j/q1s2ygNHcfTCAp12zfIromO1w3COmXrxS8hWAh7+CmZmGCIoqGcGA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz",
+            "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==",
             "dev": true,
             "dependencies": {
-                "@jest/environment": "^27.4.4",
-                "@jest/fake-timers": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/environment": "^27.5.1",
+                "@jest/fake-timers": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
-                "jest-mock": "^27.4.2",
-                "jest-util": "^27.4.2",
+                "jest-mock": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "jsdom": "^16.6.0"
             },
             "engines": {
@@ -3658,47 +3372,47 @@
             }
         },
         "node_modules/jest-environment-node": {
-            "version": "27.4.4",
-            "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.4.4.tgz",
-            "integrity": "sha512-D+v3lbJ2GjQTQR23TK0kY3vFVmSeea05giInI41HHOaJnAwOnmUHTZgUaZL+VxUB43pIzoa7PMwWtCVlIUoVoA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz",
+            "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==",
             "dev": true,
             "dependencies": {
-                "@jest/environment": "^27.4.4",
-                "@jest/fake-timers": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/environment": "^27.5.1",
+                "@jest/fake-timers": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
-                "jest-mock": "^27.4.2",
-                "jest-util": "^27.4.2"
+                "jest-mock": "^27.5.1",
+                "jest-util": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-get-type": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.4.0.tgz",
-            "integrity": "sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz",
+            "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==",
             "dev": true,
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-haste-map": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.4.5.tgz",
-            "integrity": "sha512-oJm1b5qhhPs78K24EDGifWS0dELYxnoBiDhatT/FThgB9yxqUm5F6li3Pv+Q+apMBmmPNzOBnZ7ZxWMB1Leq1Q==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz",
+            "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/graceful-fs": "^4.1.2",
                 "@types/node": "*",
                 "anymatch": "^3.0.3",
                 "fb-watchman": "^2.0.0",
-                "graceful-fs": "^4.2.4",
-                "jest-regex-util": "^27.4.0",
-                "jest-serializer": "^27.4.0",
-                "jest-util": "^27.4.2",
-                "jest-worker": "^27.4.5",
+                "graceful-fs": "^4.2.9",
+                "jest-regex-util": "^27.5.1",
+                "jest-serializer": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-worker": "^27.5.1",
                 "micromatch": "^4.0.4",
                 "walker": "^1.0.7"
             },
@@ -3710,28 +3424,27 @@
             }
         },
         "node_modules/jest-jasmine2": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.4.5.tgz",
-            "integrity": "sha512-oUnvwhJDj2LhOiUB1kdnJjkx8C5PwgUZQb9urF77mELH9DGR4e2GqpWQKBOYXWs5+uTN9BGDqRz3Aeg5Wts7aw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz",
+            "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==",
             "dev": true,
             "dependencies": {
-                "@babel/traverse": "^7.1.0",
-                "@jest/environment": "^27.4.4",
-                "@jest/source-map": "^27.4.0",
-                "@jest/test-result": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/environment": "^27.5.1",
+                "@jest/source-map": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "co": "^4.6.0",
-                "expect": "^27.4.2",
+                "expect": "^27.5.1",
                 "is-generator-fn": "^2.0.0",
-                "jest-each": "^27.4.2",
-                "jest-matcher-utils": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-runtime": "^27.4.5",
-                "jest-snapshot": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "pretty-format": "^27.4.2",
+                "jest-each": "^27.5.1",
+                "jest-matcher-utils": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-runtime": "^27.5.1",
+                "jest-snapshot": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "pretty-format": "^27.5.1",
                 "throat": "^6.0.1"
             },
             "engines": {
@@ -3739,46 +3452,46 @@
             }
         },
         "node_modules/jest-leak-detector": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.4.2.tgz",
-            "integrity": "sha512-ml0KvFYZllzPBJWDei3mDzUhyp/M4ubKebX++fPaudpe8OsxUE+m+P6ciVLboQsrzOCWDjE20/eXew9QMx/VGw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz",
+            "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==",
             "dev": true,
             "dependencies": {
-                "jest-get-type": "^27.4.0",
-                "pretty-format": "^27.4.2"
+                "jest-get-type": "^27.5.1",
+                "pretty-format": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-matcher-utils": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.4.2.tgz",
-            "integrity": "sha512-jyP28er3RRtMv+fmYC/PKG8wvAmfGcSNproVTW2Y0P/OY7/hWUOmsPfxN1jOhM+0u2xU984u2yEagGivz9OBGQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz",
+            "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==",
             "dev": true,
             "dependencies": {
                 "chalk": "^4.0.0",
-                "jest-diff": "^27.4.2",
-                "jest-get-type": "^27.4.0",
-                "pretty-format": "^27.4.2"
+                "jest-diff": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "pretty-format": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-message-util": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.4.2.tgz",
-            "integrity": "sha512-OMRqRNd9E0DkBLZpFtZkAGYOXl6ZpoMtQJWTAREJKDOFa0M6ptB7L67tp+cszMBkvSgKOhNtQp2Vbcz3ZZKo/w==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz",
+            "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==",
             "dev": true,
             "dependencies": {
                 "@babel/code-frame": "^7.12.13",
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/stack-utils": "^2.0.0",
                 "chalk": "^4.0.0",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "micromatch": "^4.0.4",
-                "pretty-format": "^27.4.2",
+                "pretty-format": "^27.5.1",
                 "slash": "^3.0.0",
                 "stack-utils": "^2.0.3"
             },
@@ -3787,12 +3500,12 @@
             }
         },
         "node_modules/jest-mock": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.4.2.tgz",
-            "integrity": "sha512-PDDPuyhoukk20JrQKeofK12hqtSka7mWH0QQuxSNgrdiPsrnYYLS6wbzu/HDlxZRzji5ylLRULeuI/vmZZDrYA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz",
+            "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*"
             },
             "engines": {
@@ -3817,27 +3530,27 @@
             }
         },
         "node_modules/jest-regex-util": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.4.0.tgz",
-            "integrity": "sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz",
+            "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==",
             "dev": true,
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-resolve": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.4.5.tgz",
-            "integrity": "sha512-xU3z1BuOz/hUhVUL+918KqUgK+skqOuUsAi7A+iwoUldK6/+PW+utK8l8cxIWT9AW7IAhGNXjSAh1UYmjULZZw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz",
+            "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "chalk": "^4.0.0",
-                "graceful-fs": "^4.2.4",
-                "jest-haste-map": "^27.4.5",
+                "graceful-fs": "^4.2.9",
+                "jest-haste-map": "^27.5.1",
                 "jest-pnp-resolver": "^1.2.2",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
+                "jest-util": "^27.5.1",
+                "jest-validate": "^27.5.1",
                 "resolve": "^1.20.0",
                 "resolve.exports": "^1.1.0",
                 "slash": "^3.0.0"
@@ -3847,45 +3560,44 @@
             }
         },
         "node_modules/jest-resolve-dependencies": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.4.5.tgz",
-            "integrity": "sha512-elEVvkvRK51y037NshtEkEnukMBWvlPzZHiL847OrIljJ8yIsujD2GXRPqDXC4rEVKbcdsy7W0FxoZb4WmEs7w==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz",
+            "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
-                "jest-regex-util": "^27.4.0",
-                "jest-snapshot": "^27.4.5"
+                "@jest/types": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-snapshot": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-runner": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.4.5.tgz",
-            "integrity": "sha512-/irauncTfmY1WkTaRQGRWcyQLzK1g98GYG/8QvIPviHgO1Fqz1JYeEIsSfF+9mc/UTA6S+IIHFgKyvUrtiBIZg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz",
+            "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==",
             "dev": true,
             "dependencies": {
-                "@jest/console": "^27.4.2",
-                "@jest/environment": "^27.4.4",
-                "@jest/test-result": "^27.4.2",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/console": "^27.5.1",
+                "@jest/environment": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "emittery": "^0.8.1",
-                "exit": "^0.1.2",
-                "graceful-fs": "^4.2.4",
-                "jest-docblock": "^27.4.0",
-                "jest-environment-jsdom": "^27.4.4",
-                "jest-environment-node": "^27.4.4",
-                "jest-haste-map": "^27.4.5",
-                "jest-leak-detector": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-resolve": "^27.4.5",
-                "jest-runtime": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-worker": "^27.4.5",
+                "graceful-fs": "^4.2.9",
+                "jest-docblock": "^27.5.1",
+                "jest-environment-jsdom": "^27.5.1",
+                "jest-environment-node": "^27.5.1",
+                "jest-haste-map": "^27.5.1",
+                "jest-leak-detector": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-runtime": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-worker": "^27.5.1",
                 "source-map-support": "^0.5.6",
                 "throat": "^6.0.1"
             },
@@ -3894,84 +3606,78 @@
             }
         },
         "node_modules/jest-runtime": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.4.5.tgz",
-            "integrity": "sha512-CIYqwuJQXHQtPd/idgrx4zgJ6iCb6uBjQq1RSAGQrw2S8XifDmoM1Ot8NRd80ooAm+ZNdHVwsktIMGlA1F1FAQ==",
-            "dev": true,
-            "dependencies": {
-                "@jest/console": "^27.4.2",
-                "@jest/environment": "^27.4.4",
-                "@jest/globals": "^27.4.4",
-                "@jest/source-map": "^27.4.0",
-                "@jest/test-result": "^27.4.2",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
-                "@types/yargs": "^16.0.0",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz",
+            "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==",
+            "dev": true,
+            "dependencies": {
+                "@jest/environment": "^27.5.1",
+                "@jest/fake-timers": "^27.5.1",
+                "@jest/globals": "^27.5.1",
+                "@jest/source-map": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "chalk": "^4.0.0",
                 "cjs-module-lexer": "^1.0.0",
                 "collect-v8-coverage": "^1.0.0",
                 "execa": "^5.0.0",
-                "exit": "^0.1.2",
                 "glob": "^7.1.3",
-                "graceful-fs": "^4.2.4",
-                "jest-haste-map": "^27.4.5",
-                "jest-message-util": "^27.4.2",
-                "jest-mock": "^27.4.2",
-                "jest-regex-util": "^27.4.0",
-                "jest-resolve": "^27.4.5",
-                "jest-snapshot": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
+                "graceful-fs": "^4.2.9",
+                "jest-haste-map": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-mock": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-snapshot": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "slash": "^3.0.0",
-                "strip-bom": "^4.0.0",
-                "yargs": "^16.2.0"
+                "strip-bom": "^4.0.0"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-serializer": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.4.0.tgz",
-            "integrity": "sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz",
+            "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==",
             "dev": true,
             "dependencies": {
                 "@types/node": "*",
-                "graceful-fs": "^4.2.4"
+                "graceful-fs": "^4.2.9"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-snapshot": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.4.5.tgz",
-            "integrity": "sha512-eCi/iM1YJFrJWiT9de4+RpWWWBqsHiYxFG9V9o/n0WXs6GpW4lUt4FAHAgFPTLPqCUVzrMQmSmTZSgQzwqR7IQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz",
+            "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==",
             "dev": true,
             "dependencies": {
                 "@babel/core": "^7.7.2",
                 "@babel/generator": "^7.7.2",
-                "@babel/parser": "^7.7.2",
                 "@babel/plugin-syntax-typescript": "^7.7.2",
                 "@babel/traverse": "^7.7.2",
                 "@babel/types": "^7.0.0",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/babel__traverse": "^7.0.4",
                 "@types/prettier": "^2.1.5",
                 "babel-preset-current-node-syntax": "^1.0.0",
                 "chalk": "^4.0.0",
-                "expect": "^27.4.2",
-                "graceful-fs": "^4.2.4",
-                "jest-diff": "^27.4.2",
-                "jest-get-type": "^27.4.0",
-                "jest-haste-map": "^27.4.5",
-                "jest-matcher-utils": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-resolve": "^27.4.5",
-                "jest-util": "^27.4.2",
+                "expect": "^27.5.1",
+                "graceful-fs": "^4.2.9",
+                "jest-diff": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "jest-haste-map": "^27.5.1",
+                "jest-matcher-utils": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "natural-compare": "^1.4.0",
-                "pretty-format": "^27.4.2",
+                "pretty-format": "^27.5.1",
                 "semver": "^7.3.2"
             },
             "engines": {
@@ -3979,16 +3685,16 @@
             }
         },
         "node_modules/jest-util": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.4.2.tgz",
-            "integrity": "sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz",
+            "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "ci-info": "^3.2.0",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "picomatch": "^2.2.3"
             },
             "engines": {
@@ -3996,26 +3702,26 @@
             }
         },
         "node_modules/jest-validate": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.4.2.tgz",
-            "integrity": "sha512-hWYsSUej+Fs8ZhOm5vhWzwSLmVaPAxRy+Mr+z5MzeaHm9AxUpXdoVMEW4R86y5gOobVfBsMFLk4Rb+QkiEpx1A==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz",
+            "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "camelcase": "^6.2.0",
                 "chalk": "^4.0.0",
-                "jest-get-type": "^27.4.0",
+                "jest-get-type": "^27.5.1",
                 "leven": "^3.1.0",
-                "pretty-format": "^27.4.2"
+                "pretty-format": "^27.5.1"
             },
             "engines": {
                 "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
             }
         },
         "node_modules/jest-validate/node_modules/camelcase": {
-            "version": "6.2.1",
-            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz",
-            "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==",
+            "version": "6.3.0",
+            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+            "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
             "dev": true,
             "engines": {
                 "node": ">=10"
@@ -4025,17 +3731,17 @@
             }
         },
         "node_modules/jest-watcher": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.4.2.tgz",
-            "integrity": "sha512-NJvMVyyBeXfDezhWzUOCOYZrUmkSCiatpjpm+nFUid74OZEHk6aMLrZAukIiFDwdbqp6mTM6Ui1w4oc+8EobQg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz",
+            "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==",
             "dev": true,
             "dependencies": {
-                "@jest/test-result": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/test-result": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "ansi-escapes": "^4.2.1",
                 "chalk": "^4.0.0",
-                "jest-util": "^27.4.2",
+                "jest-util": "^27.5.1",
                 "string-length": "^4.0.1"
             },
             "engines": {
@@ -4043,9 +3749,9 @@
             }
         },
         "node_modules/jest-worker": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz",
-            "integrity": "sha512-f2s8kEdy15cv9r7q4KkzGXvlY0JTcmCbMHZBfSQDwW77REr45IDWwd0lksDFeVHH2jJ5pqb90T77XscrjeGzzg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+            "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
             "dev": true,
             "dependencies": {
                 "@types/node": "*",
@@ -4147,6 +3853,12 @@
                 "node": ">=4"
             }
         },
+        "node_modules/json-parse-even-better-errors": {
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+            "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+            "dev": true
+        },
         "node_modules/json-schema-traverse": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -4205,6 +3917,12 @@
                 "node": ">= 0.8.0"
             }
         },
+        "node_modules/lines-and-columns": {
+            "version": "1.2.4",
+            "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+            "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+            "dev": true
+        },
         "node_modules/locate-path": {
             "version": "5.0.0",
             "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -4357,9 +4075,9 @@
             }
         },
         "node_modules/minimist": {
-            "version": "1.2.5",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-            "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+            "version": "1.2.6",
+            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+            "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
             "dev": true
         },
         "node_modules/ms": {
@@ -4380,15 +4098,6 @@
             "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
             "dev": true
         },
-        "node_modules/node-modules-regexp": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
-            "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
         "node_modules/node-releases": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.0.tgz",
@@ -4522,6 +4231,24 @@
                 "node": ">=6"
             }
         },
+        "node_modules/parse-json": {
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+            "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+            "dev": true,
+            "dependencies": {
+                "@babel/code-frame": "^7.0.0",
+                "error-ex": "^1.3.1",
+                "json-parse-even-better-errors": "^2.3.0",
+                "lines-and-columns": "^1.1.6"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/parse5": {
             "version": "6.0.1",
             "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
@@ -4589,13 +4316,10 @@
             }
         },
         "node_modules/pirates": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz",
-            "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==",
+            "version": "4.0.4",
+            "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz",
+            "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==",
             "dev": true,
-            "dependencies": {
-                "node-modules-regexp": "^1.0.0"
-            },
             "engines": {
                 "node": ">= 6"
             }
@@ -4622,24 +4346,26 @@
             }
         },
         "node_modules/prettier": {
-            "version": "2.5.1",
-            "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
-            "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+            "version": "2.6.2",
+            "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz",
+            "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==",
             "dev": true,
             "bin": {
                 "prettier": "bin-prettier.js"
             },
             "engines": {
                 "node": ">=10.13.0"
+            },
+            "funding": {
+                "url": "https://github.com/prettier/prettier?sponsor=1"
             }
         },
         "node_modules/pretty-format": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.2.tgz",
-            "integrity": "sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+            "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^27.4.2",
                 "ansi-regex": "^5.0.1",
                 "ansi-styles": "^5.0.0",
                 "react-is": "^17.0.1"
@@ -4660,15 +4386,6 @@
                 "url": "https://github.com/chalk/ansi-styles?sponsor=1"
             }
         },
-        "node_modules/progress": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
-            "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
         "node_modules/prompts": {
             "version": "2.4.2",
             "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@@ -4745,13 +4462,17 @@
             }
         },
         "node_modules/resolve": {
-            "version": "1.20.0",
-            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
-            "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+            "version": "1.22.0",
+            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
+            "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
             "dev": true,
             "dependencies": {
-                "is-core-module": "^2.2.0",
-                "path-parse": "^1.0.6"
+                "is-core-module": "^2.8.1",
+                "path-parse": "^1.0.7",
+                "supports-preserve-symlinks-flag": "^1.0.0"
+            },
+            "bin": {
+                "resolve": "bin/resolve"
             },
             "funding": {
                 "url": "https://github.com/sponsors/ljharb"
@@ -5065,6 +4786,18 @@
                 "node": ">=8"
             }
         },
+        "node_modules/supports-preserve-symlinks-flag": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+            "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+            "dev": true,
+            "engines": {
+                "node": ">= 0.4"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
         "node_modules/symbol-tree": {
             "version": "3.2.4",
             "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -5167,9 +4900,9 @@
             }
         },
         "node_modules/ts-jest": {
-            "version": "27.1.2",
-            "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.2.tgz",
-            "integrity": "sha512-eSOiJOWq6Hhs6Khzk5wKC5sgWIXgXqOCiIl1+3lfnearu58Hj4QpE5tUhQcA3xtZrELbcvAGCsd6HB8OsaVaTA==",
+            "version": "27.1.4",
+            "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz",
+            "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==",
             "dev": true,
             "dependencies": {
                 "bs-logger": "0.x",
@@ -5191,7 +4924,6 @@
                 "@babel/core": ">=7.0.0-beta.0 <8",
                 "@types/jest": "^27.0.0",
                 "babel-jest": ">=27.0.0 <28",
-                "esbuild": "~0.14.0",
                 "jest": "^27.0.0",
                 "typescript": ">=3.8 <5.0"
             },
@@ -5274,9 +5006,9 @@
             }
         },
         "node_modules/typescript": {
-            "version": "4.5.4",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
-            "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
+            "version": "4.6.3",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+            "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
             "dev": true,
             "bin": {
                 "tsc": "bin/tsc",
@@ -5311,9 +5043,9 @@
             "dev": true
         },
         "node_modules/v8-to-istanbul": {
-            "version": "8.1.0",
-            "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz",
-            "integrity": "sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==",
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz",
+            "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==",
             "dev": true,
             "dependencies": {
                 "@types/istanbul-lib-coverage": "^2.0.1",
@@ -5461,9 +5193,9 @@
             }
         },
         "node_modules/ws": {
-            "version": "7.5.6",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz",
-            "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==",
+            "version": "7.5.7",
+            "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
+            "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
             "dev": true,
             "engines": {
                 "node": ">=8.3.0"
@@ -5701,9 +5433,9 @@
             }
         },
         "@babel/helper-plugin-utils": {
-            "version": "7.16.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.5.tgz",
-            "integrity": "sha512-59KHWHXxVA9K4HNF4sbHCf+eJeFe0Te/ZFGqBT4OjXhrwvA04sGfaEGsVTdsjoszq0YTP49RC9UKe5g8uN2RwQ==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
+            "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==",
             "dev": true
         },
         "@babel/helper-replace-supers": {
@@ -5943,12 +5675,12 @@
             }
         },
         "@babel/plugin-syntax-typescript": {
-            "version": "7.16.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.5.tgz",
-            "integrity": "sha512-/d4//lZ1Vqb4mZ5xTep3dDK888j7BGM/iKqBmndBaoYAFPlPKrGU608VVBz5JeyAb6YQDjRu1UKqj86UhwWVgw==",
+            "version": "7.16.7",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz",
+            "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==",
             "dev": true,
             "requires": {
-                "@babel/helper-plugin-utils": "^7.16.5"
+                "@babel/helper-plugin-utils": "^7.16.7"
             }
         },
         "@babel/template": {
@@ -6004,28 +5736,20 @@
             "dev": true
         },
         "@eslint/eslintrc": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz",
-            "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==",
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz",
+            "integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==",
             "dev": true,
             "requires": {
                 "ajv": "^6.12.4",
                 "debug": "^4.3.2",
-                "espree": "^9.2.0",
+                "espree": "^9.3.1",
                 "globals": "^13.9.0",
-                "ignore": "^4.0.6",
+                "ignore": "^5.2.0",
                 "import-fresh": "^3.2.1",
                 "js-yaml": "^4.1.0",
                 "minimatch": "^3.0.4",
                 "strip-json-comments": "^3.1.1"
-            },
-            "dependencies": {
-                "ignore": {
-                    "version": "4.0.6",
-                    "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
-                    "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
-                    "dev": true
-                }
             }
         },
         "@humanwhocodes/config-array": {
@@ -6092,49 +5816,49 @@
             "dev": true
         },
         "@jest/console": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.4.2.tgz",
-            "integrity": "sha512-xknHThRsPB/To1FUbi6pCe43y58qFC03zfb6R7fDb/FfC7k2R3i1l+izRBJf8DI46KhYGRaF14Eo9A3qbBoixg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz",
+            "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
-                "jest-message-util": "^27.4.2",
-                "jest-util": "^27.4.2",
+                "jest-message-util": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "slash": "^3.0.0"
             }
         },
         "@jest/core": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.4.5.tgz",
-            "integrity": "sha512-3tm/Pevmi8bDsgvo73nX8p/WPng6KWlCyScW10FPEoN1HU4pwI83tJ3TsFvi1FfzsjwUlMNEPowgb/rPau/LTQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz",
+            "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==",
             "dev": true,
             "requires": {
-                "@jest/console": "^27.4.2",
-                "@jest/reporters": "^27.4.5",
-                "@jest/test-result": "^27.4.2",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/console": "^27.5.1",
+                "@jest/reporters": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "ansi-escapes": "^4.2.1",
                 "chalk": "^4.0.0",
                 "emittery": "^0.8.1",
                 "exit": "^0.1.2",
-                "graceful-fs": "^4.2.4",
-                "jest-changed-files": "^27.4.2",
-                "jest-config": "^27.4.5",
-                "jest-haste-map": "^27.4.5",
-                "jest-message-util": "^27.4.2",
-                "jest-regex-util": "^27.4.0",
-                "jest-resolve": "^27.4.5",
-                "jest-resolve-dependencies": "^27.4.5",
-                "jest-runner": "^27.4.5",
-                "jest-runtime": "^27.4.5",
-                "jest-snapshot": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
-                "jest-watcher": "^27.4.2",
+                "graceful-fs": "^4.2.9",
+                "jest-changed-files": "^27.5.1",
+                "jest-config": "^27.5.1",
+                "jest-haste-map": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-resolve-dependencies": "^27.5.1",
+                "jest-runner": "^27.5.1",
+                "jest-runtime": "^27.5.1",
+                "jest-snapshot": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-validate": "^27.5.1",
+                "jest-watcher": "^27.5.1",
                 "micromatch": "^4.0.4",
                 "rimraf": "^3.0.0",
                 "slash": "^3.0.0",
@@ -6142,68 +5866,68 @@
             }
         },
         "@jest/environment": {
-            "version": "27.4.4",
-            "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.4.4.tgz",
-            "integrity": "sha512-q+niMx7cJgt/t/b6dzLOh4W8Ef/8VyKG7hxASK39jakijJzbFBGpptx3RXz13FFV7OishQ9lTbv+dQ5K3EhfDQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz",
+            "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==",
             "dev": true,
             "requires": {
-                "@jest/fake-timers": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/fake-timers": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
-                "jest-mock": "^27.4.2"
+                "jest-mock": "^27.5.1"
             }
         },
         "@jest/fake-timers": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.4.2.tgz",
-            "integrity": "sha512-f/Xpzn5YQk5adtqBgvw1V6bF8Nx3hY0OIRRpCvWcfPl0EAjdqWPdhH3t/3XpiWZqtjIEHDyMKP9ajpva1l4Zmg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz",
+            "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@sinonjs/fake-timers": "^8.0.1",
                 "@types/node": "*",
-                "jest-message-util": "^27.4.2",
-                "jest-mock": "^27.4.2",
-                "jest-util": "^27.4.2"
+                "jest-message-util": "^27.5.1",
+                "jest-mock": "^27.5.1",
+                "jest-util": "^27.5.1"
             }
         },
         "@jest/globals": {
-            "version": "27.4.4",
-            "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.4.4.tgz",
-            "integrity": "sha512-bqpqQhW30BOreXM8bA8t8JbOQzsq/WnPTnBl+It3UxAD9J8yxEAaBEylHx1dtBapAr/UBk8GidXbzmqnee8tYQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz",
+            "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==",
             "dev": true,
             "requires": {
-                "@jest/environment": "^27.4.4",
-                "@jest/types": "^27.4.2",
-                "expect": "^27.4.2"
+                "@jest/environment": "^27.5.1",
+                "@jest/types": "^27.5.1",
+                "expect": "^27.5.1"
             }
         },
         "@jest/reporters": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.4.5.tgz",
-            "integrity": "sha512-3orsG4vi8zXuBqEoy2LbnC1kuvkg1KQUgqNxmxpQgIOQEPeV0onvZu+qDQnEoX8qTQErtqn/xzcnbpeTuOLSiA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz",
+            "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==",
             "dev": true,
             "requires": {
                 "@bcoe/v8-coverage": "^0.2.3",
-                "@jest/console": "^27.4.2",
-                "@jest/test-result": "^27.4.2",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/console": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "collect-v8-coverage": "^1.0.0",
                 "exit": "^0.1.2",
                 "glob": "^7.1.2",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "istanbul-lib-coverage": "^3.0.0",
-                "istanbul-lib-instrument": "^4.0.3",
+                "istanbul-lib-instrument": "^5.1.0",
                 "istanbul-lib-report": "^3.0.0",
                 "istanbul-lib-source-maps": "^4.0.0",
-                "istanbul-reports": "^3.0.2",
-                "jest-haste-map": "^27.4.5",
-                "jest-resolve": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-worker": "^27.4.5",
+                "istanbul-reports": "^3.1.3",
+                "jest-haste-map": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-worker": "^27.5.1",
                 "slash": "^3.0.0",
                 "source-map": "^0.6.0",
                 "string-length": "^4.0.1",
@@ -6212,67 +5936,67 @@
             }
         },
         "@jest/source-map": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.4.0.tgz",
-            "integrity": "sha512-Ntjx9jzP26Bvhbm93z/AKcPRj/9wrkI88/gK60glXDx1q+IeI0rf7Lw2c89Ch6ofonB0On/iRDreQuQ6te9pgQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz",
+            "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==",
             "dev": true,
             "requires": {
                 "callsites": "^3.0.0",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "source-map": "^0.6.0"
             }
         },
         "@jest/test-result": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.4.2.tgz",
-            "integrity": "sha512-kr+bCrra9jfTgxHXHa2UwoQjxvQk3Am6QbpAiJ5x/50LW8llOYrxILkqY0lZRW/hu8FXesnudbql263+EW9iNA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz",
+            "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==",
             "dev": true,
             "requires": {
-                "@jest/console": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/console": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/istanbul-lib-coverage": "^2.0.0",
                 "collect-v8-coverage": "^1.0.0"
             }
         },
         "@jest/test-sequencer": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.4.5.tgz",
-            "integrity": "sha512-n5woIn/1v+FT+9hniymHPARA9upYUmfi5Pw9ewVwXCDlK4F5/Gkees9v8vdjGdAIJ2MPHLHodiajLpZZanWzEQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz",
+            "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==",
             "dev": true,
             "requires": {
-                "@jest/test-result": "^27.4.2",
-                "graceful-fs": "^4.2.4",
-                "jest-haste-map": "^27.4.5",
-                "jest-runtime": "^27.4.5"
+                "@jest/test-result": "^27.5.1",
+                "graceful-fs": "^4.2.9",
+                "jest-haste-map": "^27.5.1",
+                "jest-runtime": "^27.5.1"
             }
         },
         "@jest/transform": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.4.5.tgz",
-            "integrity": "sha512-PuMet2UlZtlGzwc6L+aZmR3I7CEBpqadO03pU40l2RNY2fFJ191b9/ITB44LNOhVtsyykx0OZvj0PCyuLm7Eew==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz",
+            "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==",
             "dev": true,
             "requires": {
                 "@babel/core": "^7.1.0",
-                "@jest/types": "^27.4.2",
-                "babel-plugin-istanbul": "^6.0.0",
+                "@jest/types": "^27.5.1",
+                "babel-plugin-istanbul": "^6.1.1",
                 "chalk": "^4.0.0",
                 "convert-source-map": "^1.4.0",
                 "fast-json-stable-stringify": "^2.0.0",
-                "graceful-fs": "^4.2.4",
-                "jest-haste-map": "^27.4.5",
-                "jest-regex-util": "^27.4.0",
-                "jest-util": "^27.4.2",
+                "graceful-fs": "^4.2.9",
+                "jest-haste-map": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "micromatch": "^4.0.4",
-                "pirates": "^4.0.1",
+                "pirates": "^4.0.4",
                 "slash": "^3.0.0",
                 "source-map": "^0.6.1",
                 "write-file-atomic": "^3.0.0"
             }
         },
         "@jest/types": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.4.2.tgz",
-            "integrity": "sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz",
+            "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==",
             "dev": true,
             "requires": {
                 "@types/istanbul-lib-coverage": "^2.0.0",
@@ -6333,9 +6057,9 @@
             "dev": true
         },
         "@types/babel__core": {
-            "version": "7.1.16",
-            "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz",
-            "integrity": "sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==",
+            "version": "7.1.18",
+            "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.18.tgz",
+            "integrity": "sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==",
             "dev": true,
             "requires": {
                 "@babel/parser": "^7.1.0",
@@ -6346,9 +6070,9 @@
             }
         },
         "@types/babel__generator": {
-            "version": "7.6.3",
-            "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz",
-            "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==",
+            "version": "7.6.4",
+            "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
+            "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
             "dev": true,
             "requires": {
                 "@babel/types": "^7.0.0"
@@ -6413,31 +6137,31 @@
             }
         },
         "@types/jest": {
-            "version": "27.0.3",
-            "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.3.tgz",
-            "integrity": "sha512-cmmwv9t7gBYt7hNKH5Spu7Kuu/DotGa+Ff+JGRKZ4db5eh8PnKS4LuebJ3YLUoyOyIHraTGyULn23YtEAm0VSg==",
+            "version": "27.4.1",
+            "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz",
+            "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==",
             "dev": true,
             "requires": {
-                "jest-diff": "^27.0.0",
+                "jest-matcher-utils": "^27.0.0",
                 "pretty-format": "^27.0.0"
             }
         },
         "@types/json-schema": {
-            "version": "7.0.9",
-            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
-            "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
+            "version": "7.0.11",
+            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+            "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
             "dev": true
         },
         "@types/node": {
-            "version": "17.0.4",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.4.tgz",
-            "integrity": "sha512-6xwbrW4JJiJLgF+zNypN5wr2ykM9/jHcL7rQ8fZe2vuftggjzZeRSM4OwRc6Xk8qWjwJ99qVHo/JgOGmomWRog==",
+            "version": "17.0.29",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.29.tgz",
+            "integrity": "sha512-tx5jMmMFwx7wBwq/V7OohKDVb/JwJU5qCVkeLMh1//xycAJ/ESuw9aJ9SEtlCZDYi2pBfe4JkisSoAtbOsBNAA==",
             "dev": true
         },
         "@types/prettier": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.2.tgz",
-            "integrity": "sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA==",
+            "version": "2.4.3",
+            "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.3.tgz",
+            "integrity": "sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w==",
             "dev": true
         },
         "@types/stack-utils": {
@@ -6462,13 +6186,14 @@
             "dev": true
         },
         "@typescript-eslint/eslint-plugin": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.8.0.tgz",
-            "integrity": "sha512-spu1UW7QuBn0nJ6+psnfCc3iVoQAifjKORgBngKOmC8U/1tbe2YJMzYQqDGYB4JCss7L8+RM2kKLb1B1Aw9BNA==",
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.21.0.tgz",
+            "integrity": "sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg==",
             "dev": true,
             "requires": {
-                "@typescript-eslint/experimental-utils": "5.8.0",
-                "@typescript-eslint/scope-manager": "5.8.0",
+                "@typescript-eslint/scope-manager": "5.21.0",
+                "@typescript-eslint/type-utils": "5.21.0",
+                "@typescript-eslint/utils": "5.21.0",
                 "debug": "^4.3.2",
                 "functional-red-black-tree": "^1.0.1",
                 "ignore": "^5.1.8",
@@ -6477,56 +6202,53 @@
                 "tsutils": "^3.21.0"
             }
         },
-        "@typescript-eslint/experimental-utils": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.8.0.tgz",
-            "integrity": "sha512-KN5FvNH71bhZ8fKtL+lhW7bjm7cxs1nt+hrDZWIqb6ViCffQcWyLunGrgvISgkRojIDcXIsH+xlFfI4RCDA0xA==",
+        "@typescript-eslint/parser": {
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.21.0.tgz",
+            "integrity": "sha512-8RUwTO77hstXUr3pZoWZbRQUxXcSXafZ8/5gpnQCfXvgmP9gpNlRGlWzvfbEQ14TLjmtU8eGnONkff8U2ui2Eg==",
             "dev": true,
             "requires": {
-                "@types/json-schema": "^7.0.9",
-                "@typescript-eslint/scope-manager": "5.8.0",
-                "@typescript-eslint/types": "5.8.0",
-                "@typescript-eslint/typescript-estree": "5.8.0",
-                "eslint-scope": "^5.1.1",
-                "eslint-utils": "^3.0.0"
+                "@typescript-eslint/scope-manager": "5.21.0",
+                "@typescript-eslint/types": "5.21.0",
+                "@typescript-eslint/typescript-estree": "5.21.0",
+                "debug": "^4.3.2"
             }
         },
-        "@typescript-eslint/parser": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.8.0.tgz",
-            "integrity": "sha512-Gleacp/ZhRtJRYs5/T8KQR3pAQjQI89Dn/k+OzyCKOsLiZH2/Vh60cFBTnFsHNI6WAD+lNUo/xGZ4NeA5u0Ipw==",
+        "@typescript-eslint/scope-manager": {
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.21.0.tgz",
+            "integrity": "sha512-XTX0g0IhvzcH/e3393SvjRCfYQxgxtYzL3UREteUneo72EFlt7UNoiYnikUtmGVobTbhUDByhJ4xRBNe+34kOQ==",
             "dev": true,
             "requires": {
-                "@typescript-eslint/scope-manager": "5.8.0",
-                "@typescript-eslint/types": "5.8.0",
-                "@typescript-eslint/typescript-estree": "5.8.0",
-                "debug": "^4.3.2"
+                "@typescript-eslint/types": "5.21.0",
+                "@typescript-eslint/visitor-keys": "5.21.0"
             }
         },
-        "@typescript-eslint/scope-manager": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.8.0.tgz",
-            "integrity": "sha512-x82CYJsLOjPCDuFFEbS6e7K1QEWj7u5Wk1alw8A+gnJiYwNnDJk0ib6PCegbaPMjrfBvFKa7SxE3EOnnIQz2Gg==",
+        "@typescript-eslint/type-utils": {
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.21.0.tgz",
+            "integrity": "sha512-MxmLZj0tkGlkcZCSE17ORaHl8Th3JQwBzyXL/uvC6sNmu128LsgjTX0NIzy+wdH2J7Pd02GN8FaoudJntFvSOw==",
             "dev": true,
             "requires": {
-                "@typescript-eslint/types": "5.8.0",
-                "@typescript-eslint/visitor-keys": "5.8.0"
+                "@typescript-eslint/utils": "5.21.0",
+                "debug": "^4.3.2",
+                "tsutils": "^3.21.0"
             }
         },
         "@typescript-eslint/types": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.8.0.tgz",
-            "integrity": "sha512-LdCYOqeqZWqCMOmwFnum6YfW9F3nKuxJiR84CdIRN5nfHJ7gyvGpXWqL/AaW0k3Po0+wm93ARAsOdzlZDPCcXg==",
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.21.0.tgz",
+            "integrity": "sha512-XnOOo5Wc2cBlq8Lh5WNvAgHzpjnEzxn4CJBwGkcau7b/tZ556qrWXQz4DJyChYg8JZAD06kczrdgFPpEQZfDsA==",
             "dev": true
         },
         "@typescript-eslint/typescript-estree": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.8.0.tgz",
-            "integrity": "sha512-srfeZ3URdEcUsSLbkOFqS7WoxOqn8JNil2NSLO9O+I2/Uyc85+UlfpEvQHIpj5dVts7KKOZnftoJD/Fdv0L7nQ==",
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.21.0.tgz",
+            "integrity": "sha512-Y8Y2T2FNvm08qlcoSMoNchh9y2Uj3QmjtwNMdRQkcFG7Muz//wfJBGBxh8R7HAGQFpgYpdHqUpEoPQk+q9Kjfg==",
             "dev": true,
             "requires": {
-                "@typescript-eslint/types": "5.8.0",
-                "@typescript-eslint/visitor-keys": "5.8.0",
+                "@typescript-eslint/types": "5.21.0",
+                "@typescript-eslint/visitor-keys": "5.21.0",
                 "debug": "^4.3.2",
                 "globby": "^11.0.4",
                 "is-glob": "^4.0.3",
@@ -6534,13 +6256,27 @@
                 "tsutils": "^3.21.0"
             }
         },
+        "@typescript-eslint/utils": {
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.21.0.tgz",
+            "integrity": "sha512-q/emogbND9wry7zxy7VYri+7ydawo2HDZhRZ5k6yggIvXa7PvBbAAZ4PFH/oZLem72ezC4Pr63rJvDK/sTlL8Q==",
+            "dev": true,
+            "requires": {
+                "@types/json-schema": "^7.0.9",
+                "@typescript-eslint/scope-manager": "5.21.0",
+                "@typescript-eslint/types": "5.21.0",
+                "@typescript-eslint/typescript-estree": "5.21.0",
+                "eslint-scope": "^5.1.1",
+                "eslint-utils": "^3.0.0"
+            }
+        },
         "@typescript-eslint/visitor-keys": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.8.0.tgz",
-            "integrity": "sha512-+HDIGOEMnqbxdAHegxvnOqESUH6RWFRR2b8qxP1W9CZnnYh4Usz6MBL+2KMAgPk/P0o9c1HqnYtwzVH6GTIqug==",
+            "version": "5.21.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz",
+            "integrity": "sha512-SX8jNN+iHqAF0riZQMkm7e8+POXa/fXw5cxL+gjpyP+FI+JVNhii53EmQgDAfDcBpFekYSlO0fGytMQwRiMQCA==",
             "dev": true,
             "requires": {
-                "@typescript-eslint/types": "5.8.0",
+                "@typescript-eslint/types": "5.21.0",
                 "eslint-visitor-keys": "^3.0.0"
             }
         },
@@ -6551,9 +6287,9 @@
             "dev": true
         },
         "acorn": {
-            "version": "8.6.0",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz",
-            "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==",
+            "version": "8.7.0",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
+            "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
             "dev": true
         },
         "acorn-globals": {
@@ -6608,12 +6344,6 @@
                 "uri-js": "^4.2.2"
             }
         },
-        "ansi-colors": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
-            "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
-            "dev": true
-        },
         "ansi-escapes": {
             "version": "4.3.2",
             "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
@@ -6675,38 +6405,38 @@
             "dev": true
         },
         "babel-jest": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.4.5.tgz",
-            "integrity": "sha512-3uuUTjXbgtODmSv/DXO9nZfD52IyC2OYTFaXGRzL0kpykzroaquCrD5+lZNafTvZlnNqZHt5pb0M08qVBZnsnA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz",
+            "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==",
             "dev": true,
             "requires": {
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/babel__core": "^7.1.14",
-                "babel-plugin-istanbul": "^6.0.0",
-                "babel-preset-jest": "^27.4.0",
+                "babel-plugin-istanbul": "^6.1.1",
+                "babel-preset-jest": "^27.5.1",
                 "chalk": "^4.0.0",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "slash": "^3.0.0"
             }
         },
         "babel-plugin-istanbul": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz",
-            "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==",
+            "version": "6.1.1",
+            "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+            "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
             "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@istanbuljs/load-nyc-config": "^1.0.0",
                 "@istanbuljs/schema": "^0.1.2",
-                "istanbul-lib-instrument": "^4.0.0",
+                "istanbul-lib-instrument": "^5.0.4",
                 "test-exclude": "^6.0.0"
             }
         },
         "babel-plugin-jest-hoist": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.4.0.tgz",
-            "integrity": "sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz",
+            "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==",
             "dev": true,
             "requires": {
                 "@babel/template": "^7.3.3",
@@ -6736,12 +6466,12 @@
             }
         },
         "babel-preset-jest": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz",
-            "integrity": "sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz",
+            "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==",
             "dev": true,
             "requires": {
-                "babel-plugin-jest-hoist": "^27.4.0",
+                "babel-plugin-jest-hoist": "^27.5.1",
                 "babel-preset-current-node-syntax": "^1.0.0"
             }
         },
@@ -6984,9 +6714,9 @@
             }
         },
         "css-what": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
-            "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw=="
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+            "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
         },
         "cssom": {
             "version": "0.4.4",
@@ -7068,9 +6798,9 @@
             "dev": true
         },
         "diff-sequences": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.4.0.tgz",
-            "integrity": "sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz",
+            "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==",
             "dev": true
         },
         "dir-glob": {
@@ -7092,19 +6822,19 @@
             }
         },
         "dom-serializer": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
-            "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+            "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
             "requires": {
-                "domelementtype": "^2.0.1",
-                "domhandler": "^4.2.0",
-                "entities": "^2.0.0"
+                "domelementtype": "^2.3.0",
+                "domhandler": "^5.0.2",
+                "entities": "^4.2.0"
             }
         },
         "domelementtype": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-            "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+            "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
         },
         "domexception": {
             "version": "2.0.1",
@@ -7124,21 +6854,21 @@
             }
         },
         "domhandler": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
-            "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
+            "version": "5.0.2",
+            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.2.tgz",
+            "integrity": "sha512-pr8ToPIuwBonzUy42STpc5Cf0m69zsQ7gtCLLvKrTbhVRnRohT2pLiJmGp3PAh16nDVWpYpcRpdjuk1vFmnQUg==",
             "requires": {
-                "domelementtype": "^2.2.0"
+                "domelementtype": "^2.3.0"
             }
         },
         "domutils": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
-            "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
+            "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
             "requires": {
-                "dom-serializer": "^1.0.1",
-                "domelementtype": "^2.2.0",
-                "domhandler": "^4.2.0"
+                "dom-serializer": "^2.0.0",
+                "domelementtype": "^2.3.0",
+                "domhandler": "^5.0.1"
             }
         },
         "electron-to-chromium": {
@@ -7159,182 +6889,19 @@
             "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
             "dev": true
         },
-        "enquirer": {
-            "version": "2.3.6",
-            "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
-            "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
-            "dev": true,
-            "requires": {
-                "ansi-colors": "^4.1.1"
-            }
-        },
         "entities": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-            "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
-        },
-        "esbuild": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.2.tgz",
-            "integrity": "sha512-l076A6o/PIgcyM24s0dWmDI/b8RQf41uWoJu9I0M71CtW/YSw5T5NUeXxs5lo2tFQD+O4CW4nBHJXx3OY5NpXg==",
-            "dev": true,
-            "optional": true,
-            "peer": true,
-            "requires": {
-                "esbuild-android-arm64": "0.14.2",
-                "esbuild-darwin-64": "0.14.2",
-                "esbuild-darwin-arm64": "0.14.2",
-                "esbuild-freebsd-64": "0.14.2",
-                "esbuild-freebsd-arm64": "0.14.2",
-                "esbuild-linux-32": "0.14.2",
-                "esbuild-linux-64": "0.14.2",
-                "esbuild-linux-arm": "0.14.2",
-                "esbuild-linux-arm64": "0.14.2",
-                "esbuild-linux-mips64le": "0.14.2",
-                "esbuild-linux-ppc64le": "0.14.2",
-                "esbuild-netbsd-64": "0.14.2",
-                "esbuild-openbsd-64": "0.14.2",
-                "esbuild-sunos-64": "0.14.2",
-                "esbuild-windows-32": "0.14.2",
-                "esbuild-windows-64": "0.14.2",
-                "esbuild-windows-arm64": "0.14.2"
-            }
-        },
-        "esbuild-android-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.2.tgz",
-            "integrity": "sha512-hEixaKMN3XXCkoe+0WcexO4CcBVU5DCSUT+7P8JZiWZCbAjSkc9b6Yz2X5DSfQmRCtI/cQRU6TfMYrMQ5NBfdw==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-darwin-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.2.tgz",
-            "integrity": "sha512-Uq8t0cbJQkxkQdbUfOl2wZqZ/AtLZjvJulR1HHnc96UgyzG9YlCLSDMiqjM+NANEy7/zzvwKJsy3iNC9wwqLJA==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-darwin-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.2.tgz",
-            "integrity": "sha512-619MSa17sr7YCIrUj88KzQu2ESA4jKYtIYfLU/smX6qNgxQt3Y/gzM4s6sgJ4fPQzirvmXgcHv1ZNQAs/Xh48A==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-freebsd-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.2.tgz",
-            "integrity": "sha512-aP6FE/ZsChZpUV6F3HE3x1Pz0paoYXycJ7oLt06g0G9dhJKknPawXCqQg/WMyD+ldCEZfo7F1kavenPdIT/SGQ==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-freebsd-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.2.tgz",
-            "integrity": "sha512-LSm98WTb1QIhyS83+Po0KTpZNdd2XpVpI9ua5rLWqKWbKeNRFwOsjeiuwBaRNc+O32s9oC2ZMefETxHBV6VNkQ==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-linux-32": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.2.tgz",
-            "integrity": "sha512-8VxnNEyeUbiGflTKcuVc5JEPTqXfsx2O6ABwUbfS1Hp26lYPRPC7pKQK5Dxa0MBejGc50jy7YZae3EGQUQ8EkQ==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-linux-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.2.tgz",
-            "integrity": "sha512-4bzMS2dNxOJoFIiHId4w+tqQzdnsch71JJV1qZnbnErSFWcR9lRgpSqWnTTFtv6XM+MvltRzSXC5wQ7AEBY6Hg==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-linux-arm": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.2.tgz",
-            "integrity": "sha512-PaylahvMHhH8YMfJPMKEqi64qA0Su+d4FNfHKvlKes/2dUe4QxgbwXT9oLVgy8iJdcFMrO7By4R8fS8S0p8aVQ==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-linux-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.2.tgz",
-            "integrity": "sha512-RlIVp0RwJrdtasDF1vTFueLYZ8WuFzxoQ1OoRFZOTyJHCGCNgh7xJIC34gd7B7+RT0CzLBB4LcM5n0LS+hIoww==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-linux-mips64le": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.2.tgz",
-            "integrity": "sha512-Fdwrq2roFnO5oetIiUQQueZ3+5soCxBSJswg3MvYaXDomj47BN6oAWMZgLrFh1oVrtWrxSDLCJBenYdbm2s+qQ==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-linux-ppc64le": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.2.tgz",
-            "integrity": "sha512-vxptskw8JfCDD9QqpRO0XnsM1osuWeRjPaXX1TwdveLogYsbdFtcuiuK/4FxGiNMUr1ojtnCS2rMPbY8puc5NA==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-netbsd-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.2.tgz",
-            "integrity": "sha512-I8+LzYK5iSNpspS9eCV9sW67Rj8FgMHimGri4mKiGAmN0pNfx+hFX146rYtzGtewuxKtTsPywWteHx+hPRLDsw==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-openbsd-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.2.tgz",
-            "integrity": "sha512-120HgMe9elidWUvM2E6mMf0csrGwx8sYDqUIJugyMy1oHm+/nT08bTAVXuwYG/rkMIqsEO9AlMxuYnwR6En/3Q==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-sunos-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.2.tgz",
-            "integrity": "sha512-Q3xcf9Uyfra9UuCFxoLixVvdigo0daZaKJ97TL2KNA4bxRUPK18wwGUk3AxvgDQZpRmg82w9PnkaNYo7a+24ow==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-windows-32": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.2.tgz",
-            "integrity": "sha512-TW7O49tPsrq+N1sW8mb3m24j/iDGa4xzAZH4wHWwoIzgtZAYPKC0hpIhufRRG/LA30bdMChO9pjJZ5mtcybtBQ==",
-            "dev": true,
-            "optional": true,
-            "peer": true
-        },
-        "esbuild-windows-64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.2.tgz",
-            "integrity": "sha512-Rym6ViMNmi1E2QuQMWy0AFAfdY0wGwZD73BnzlsQBX5hZBuy/L+Speh7ucUZ16gwsrMM9v86icZUDrSN/lNBKg==",
-            "dev": true,
-            "optional": true,
-            "peer": true
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz",
+            "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg=="
         },
-        "esbuild-windows-arm64": {
-            "version": "0.14.2",
-            "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.2.tgz",
-            "integrity": "sha512-ZrLbhr0vX5Em/P1faMnHucjVVWPS+m3tktAtz93WkMZLmbRJevhiW1y4CbulBd2z0MEdXZ6emDa1zFHq5O5bSA==",
+        "error-ex": {
+            "version": "1.3.2",
+            "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+            "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
             "dev": true,
-            "optional": true,
-            "peer": true
+            "requires": {
+                "is-arrayish": "^0.2.1"
+            }
         },
         "escalade": {
             "version": "3.1.1",
@@ -7409,24 +6976,23 @@
             }
         },
         "eslint": {
-            "version": "8.5.0",
-            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz",
-            "integrity": "sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg==",
+            "version": "8.14.0",
+            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz",
+            "integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==",
             "dev": true,
             "requires": {
-                "@eslint/eslintrc": "^1.0.5",
+                "@eslint/eslintrc": "^1.2.2",
                 "@humanwhocodes/config-array": "^0.9.2",
                 "ajv": "^6.10.0",
                 "chalk": "^4.0.0",
                 "cross-spawn": "^7.0.2",
                 "debug": "^4.3.2",
                 "doctrine": "^3.0.0",
-                "enquirer": "^2.3.5",
                 "escape-string-regexp": "^4.0.0",
-                "eslint-scope": "^7.1.0",
+                "eslint-scope": "^7.1.1",
                 "eslint-utils": "^3.0.0",
-                "eslint-visitor-keys": "^3.1.0",
-                "espree": "^9.2.0",
+                "eslint-visitor-keys": "^3.3.0",
+                "espree": "^9.3.1",
                 "esquery": "^1.4.0",
                 "esutils": "^2.0.2",
                 "fast-deep-equal": "^3.1.3",
@@ -7434,7 +7000,7 @@
                 "functional-red-black-tree": "^1.0.1",
                 "glob-parent": "^6.0.1",
                 "globals": "^13.6.0",
-                "ignore": "^4.0.6",
+                "ignore": "^5.2.0",
                 "import-fresh": "^3.0.0",
                 "imurmurhash": "^0.1.4",
                 "is-glob": "^4.0.0",
@@ -7445,9 +7011,7 @@
                 "minimatch": "^3.0.4",
                 "natural-compare": "^1.4.0",
                 "optionator": "^0.9.1",
-                "progress": "^2.0.0",
                 "regexpp": "^3.2.0",
-                "semver": "^7.2.1",
                 "strip-ansi": "^6.0.1",
                 "strip-json-comments": "^3.1.0",
                 "text-table": "^0.2.0",
@@ -7455,9 +7019,9 @@
             },
             "dependencies": {
                 "eslint-scope": {
-                    "version": "7.1.0",
-                    "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz",
-                    "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==",
+                    "version": "7.1.1",
+                    "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+                    "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
                     "dev": true,
                     "requires": {
                         "esrecurse": "^4.3.0",
@@ -7469,19 +7033,13 @@
                     "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
                     "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
                     "dev": true
-                },
-                "ignore": {
-                    "version": "4.0.6",
-                    "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
-                    "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
-                    "dev": true
                 }
             }
         },
         "eslint-config-prettier": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz",
-            "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==",
+            "version": "8.5.0",
+            "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
+            "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
             "dev": true,
             "requires": {}
         },
@@ -7513,20 +7071,20 @@
             }
         },
         "eslint-visitor-keys": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz",
-            "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==",
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+            "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
             "dev": true
         },
         "espree": {
-            "version": "9.2.0",
-            "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz",
-            "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==",
+            "version": "9.3.1",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
+            "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
             "dev": true,
             "requires": {
-                "acorn": "^8.6.0",
+                "acorn": "^8.7.0",
                 "acorn-jsx": "^5.3.1",
-                "eslint-visitor-keys": "^3.1.0"
+                "eslint-visitor-keys": "^3.3.0"
             }
         },
         "esprima": {
@@ -7605,25 +7163,15 @@
             "dev": true
         },
         "expect": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/expect/-/expect-27.4.2.tgz",
-            "integrity": "sha512-BjAXIDC6ZOW+WBFNg96J22D27Nq5ohn+oGcuP2rtOtcjuxNoV9McpQ60PcQWhdFOSBIQdR72e+4HdnbZTFSTyg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz",
+            "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
-                "ansi-styles": "^5.0.0",
-                "jest-get-type": "^27.4.0",
-                "jest-matcher-utils": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-regex-util": "^27.4.0"
-            },
-            "dependencies": {
-                "ansi-styles": {
-                    "version": "5.2.0",
-                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
-                    "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
-                    "dev": true
-                }
+                "@jest/types": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "jest-matcher-utils": "^27.5.1",
+                "jest-message-util": "^27.5.1"
             }
         },
         "fast-deep-equal": {
@@ -7814,9 +7362,9 @@
             }
         },
         "globals": {
-            "version": "13.12.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
-            "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
+            "version": "13.13.0",
+            "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
+            "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
             "dev": true,
             "requires": {
                 "type-fest": "^0.20.2"
@@ -7837,9 +7385,9 @@
             }
         },
         "graceful-fs": {
-            "version": "4.2.8",
-            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
-            "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
+            "version": "4.2.9",
+            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
+            "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
             "dev": true
         },
         "has": {
@@ -7873,23 +7421,15 @@
             "dev": true
         },
         "htmlparser2": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz",
-            "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==",
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.0.tgz",
+            "integrity": "sha512-4wbT2/t9kITgTLhFoPPzIh4xW/fDXE4NKQDcBhWC0fPCraSA5K26W8D09K5NAqNqsBp/f7wDN2LR2rA4GhlGhA==",
             "dev": true,
             "requires": {
-                "domelementtype": "^2.0.1",
-                "domhandler": "^4.2.2",
-                "domutils": "^2.8.0",
-                "entities": "^3.0.1"
-            },
-            "dependencies": {
-                "entities": {
-                    "version": "3.0.1",
-                    "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
-                    "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
-                    "dev": true
-                }
+                "domelementtype": "^2.3.0",
+                "domhandler": "^5.0.2",
+                "domutils": "^3.0.1",
+                "entities": "^4.3.0"
             }
         },
         "http-proxy-agent": {
@@ -7929,9 +7469,9 @@
             }
         },
         "ignore": {
-            "version": "5.1.8",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
-            "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+            "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
             "dev": true
         },
         "import-fresh": {
@@ -7945,9 +7485,9 @@
             }
         },
         "import-local": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz",
-            "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==",
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+            "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
             "dev": true,
             "requires": {
                 "pkg-dir": "^4.2.0",
@@ -7976,10 +7516,16 @@
             "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
             "dev": true
         },
+        "is-arrayish": {
+            "version": "0.2.1",
+            "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+            "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+            "dev": true
+        },
         "is-core-module": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
-            "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==",
+            "version": "2.8.1",
+            "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
+            "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
             "dev": true,
             "requires": {
                 "has": "^1.0.3"
@@ -8043,20 +7589,21 @@
             "dev": true
         },
         "istanbul-lib-coverage": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.2.tgz",
-            "integrity": "sha512-o5+eTUYzCJ11/+JhW5/FUCdfsdoYVdQ/8I/OveE2XsjehYn5DdeSnNQAbjYaO8gQ6hvGTN6GM6ddQqpTVG5j8g==",
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
+            "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
             "dev": true
         },
         "istanbul-lib-instrument": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
-            "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz",
+            "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==",
             "dev": true,
             "requires": {
-                "@babel/core": "^7.7.5",
+                "@babel/core": "^7.12.3",
+                "@babel/parser": "^7.14.7",
                 "@istanbuljs/schema": "^0.1.2",
-                "istanbul-lib-coverage": "^3.0.0",
+                "istanbul-lib-coverage": "^3.2.0",
                 "semver": "^6.3.0"
             },
             "dependencies": {
@@ -8091,9 +7638,9 @@
             }
         },
         "istanbul-reports": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.1.tgz",
-            "integrity": "sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw==",
+            "version": "3.1.4",
+            "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz",
+            "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==",
             "dev": true,
             "requires": {
                 "html-escaper": "^2.0.0",
@@ -8101,266 +7648,267 @@
             }
         },
         "jest": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest/-/jest-27.4.5.tgz",
-            "integrity": "sha512-uT5MiVN3Jppt314kidCk47MYIRilJjA/l2mxwiuzzxGUeJIvA8/pDaJOAX5KWvjAo7SCydcW0/4WEtgbLMiJkg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
+            "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==",
             "dev": true,
             "requires": {
-                "@jest/core": "^27.4.5",
+                "@jest/core": "^27.5.1",
                 "import-local": "^3.0.2",
-                "jest-cli": "^27.4.5"
+                "jest-cli": "^27.5.1"
             }
         },
         "jest-changed-files": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.4.2.tgz",
-            "integrity": "sha512-/9x8MjekuzUQoPjDHbBiXbNEBauhrPU2ct7m8TfCg69ywt1y/N+yYwGh3gCpnqUS3klYWDU/lSNgv+JhoD2k1A==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz",
+            "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "execa": "^5.0.0",
                 "throat": "^6.0.1"
             }
         },
         "jest-circus": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.4.5.tgz",
-            "integrity": "sha512-eTNWa9wsvBwPykhMMShheafbwyakcdHZaEYh5iRrQ0PFJxkDP/e3U/FvzGuKWu2WpwUA3C3hPlfpuzvOdTVqnw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz",
+            "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==",
             "dev": true,
             "requires": {
-                "@jest/environment": "^27.4.4",
-                "@jest/test-result": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/environment": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "co": "^4.6.0",
                 "dedent": "^0.7.0",
-                "expect": "^27.4.2",
+                "expect": "^27.5.1",
                 "is-generator-fn": "^2.0.0",
-                "jest-each": "^27.4.2",
-                "jest-matcher-utils": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-runtime": "^27.4.5",
-                "jest-snapshot": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "pretty-format": "^27.4.2",
+                "jest-each": "^27.5.1",
+                "jest-matcher-utils": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-runtime": "^27.5.1",
+                "jest-snapshot": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "pretty-format": "^27.5.1",
                 "slash": "^3.0.0",
                 "stack-utils": "^2.0.3",
                 "throat": "^6.0.1"
             }
         },
         "jest-cli": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.4.5.tgz",
-            "integrity": "sha512-hrky3DSgE0u7sQxaCL7bdebEPHx5QzYmrGuUjaPLmPE8jx5adtvGuOlRspvMoVLTTDOHRnZDoRLYJuA+VCI7Hg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz",
+            "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==",
             "dev": true,
             "requires": {
-                "@jest/core": "^27.4.5",
-                "@jest/test-result": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/core": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "chalk": "^4.0.0",
                 "exit": "^0.1.2",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "import-local": "^3.0.2",
-                "jest-config": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
+                "jest-config": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-validate": "^27.5.1",
                 "prompts": "^2.0.1",
                 "yargs": "^16.2.0"
             }
         },
         "jest-config": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.4.5.tgz",
-            "integrity": "sha512-t+STVJtPt+fpqQ8GBw850NtSQbnDOw/UzdPfzDaHQ48/AylQlW7LHj3dH+ndxhC1UxJ0Q3qkq7IH+nM1skwTwA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz",
+            "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==",
             "dev": true,
             "requires": {
-                "@babel/core": "^7.1.0",
-                "@jest/test-sequencer": "^27.4.5",
-                "@jest/types": "^27.4.2",
-                "babel-jest": "^27.4.5",
+                "@babel/core": "^7.8.0",
+                "@jest/test-sequencer": "^27.5.1",
+                "@jest/types": "^27.5.1",
+                "babel-jest": "^27.5.1",
                 "chalk": "^4.0.0",
                 "ci-info": "^3.2.0",
                 "deepmerge": "^4.2.2",
                 "glob": "^7.1.1",
-                "graceful-fs": "^4.2.4",
-                "jest-circus": "^27.4.5",
-                "jest-environment-jsdom": "^27.4.4",
-                "jest-environment-node": "^27.4.4",
-                "jest-get-type": "^27.4.0",
-                "jest-jasmine2": "^27.4.5",
-                "jest-regex-util": "^27.4.0",
-                "jest-resolve": "^27.4.5",
-                "jest-runner": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
+                "graceful-fs": "^4.2.9",
+                "jest-circus": "^27.5.1",
+                "jest-environment-jsdom": "^27.5.1",
+                "jest-environment-node": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "jest-jasmine2": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-runner": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-validate": "^27.5.1",
                 "micromatch": "^4.0.4",
-                "pretty-format": "^27.4.2",
-                "slash": "^3.0.0"
+                "parse-json": "^5.2.0",
+                "pretty-format": "^27.5.1",
+                "slash": "^3.0.0",
+                "strip-json-comments": "^3.1.1"
             }
         },
         "jest-diff": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.4.2.tgz",
-            "integrity": "sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz",
+            "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==",
             "dev": true,
             "requires": {
                 "chalk": "^4.0.0",
-                "diff-sequences": "^27.4.0",
-                "jest-get-type": "^27.4.0",
-                "pretty-format": "^27.4.2"
+                "diff-sequences": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "pretty-format": "^27.5.1"
             }
         },
         "jest-docblock": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.4.0.tgz",
-            "integrity": "sha512-7TBazUdCKGV7svZ+gh7C8esAnweJoG+SvcF6Cjqj4l17zA2q1cMwx2JObSioubk317H+cjcHgP+7fTs60paulg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz",
+            "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==",
             "dev": true,
             "requires": {
                 "detect-newline": "^3.0.0"
             }
         },
         "jest-each": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.4.2.tgz",
-            "integrity": "sha512-53V2MNyW28CTruB3lXaHNk6PkiIFuzdOC9gR3C6j8YE/ACfrPnz+slB0s17AgU1TtxNzLuHyvNlLJ+8QYw9nBg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz",
+            "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "chalk": "^4.0.0",
-                "jest-get-type": "^27.4.0",
-                "jest-util": "^27.4.2",
-                "pretty-format": "^27.4.2"
+                "jest-get-type": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "pretty-format": "^27.5.1"
             }
         },
         "jest-environment-jsdom": {
-            "version": "27.4.4",
-            "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.4.4.tgz",
-            "integrity": "sha512-cYR3ndNfHBqQgFvS1RL7dNqSvD//K56j/q1s2ygNHcfTCAp12zfIromO1w3COmXrxS8hWAh7+CmZmGCIoqGcGA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz",
+            "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==",
             "dev": true,
             "requires": {
-                "@jest/environment": "^27.4.4",
-                "@jest/fake-timers": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/environment": "^27.5.1",
+                "@jest/fake-timers": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
-                "jest-mock": "^27.4.2",
-                "jest-util": "^27.4.2",
+                "jest-mock": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "jsdom": "^16.6.0"
             }
         },
         "jest-environment-node": {
-            "version": "27.4.4",
-            "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.4.4.tgz",
-            "integrity": "sha512-D+v3lbJ2GjQTQR23TK0kY3vFVmSeea05giInI41HHOaJnAwOnmUHTZgUaZL+VxUB43pIzoa7PMwWtCVlIUoVoA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz",
+            "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==",
             "dev": true,
             "requires": {
-                "@jest/environment": "^27.4.4",
-                "@jest/fake-timers": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/environment": "^27.5.1",
+                "@jest/fake-timers": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
-                "jest-mock": "^27.4.2",
-                "jest-util": "^27.4.2"
+                "jest-mock": "^27.5.1",
+                "jest-util": "^27.5.1"
             }
         },
         "jest-get-type": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.4.0.tgz",
-            "integrity": "sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz",
+            "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==",
             "dev": true
         },
         "jest-haste-map": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.4.5.tgz",
-            "integrity": "sha512-oJm1b5qhhPs78K24EDGifWS0dELYxnoBiDhatT/FThgB9yxqUm5F6li3Pv+Q+apMBmmPNzOBnZ7ZxWMB1Leq1Q==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz",
+            "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/graceful-fs": "^4.1.2",
                 "@types/node": "*",
                 "anymatch": "^3.0.3",
                 "fb-watchman": "^2.0.0",
                 "fsevents": "^2.3.2",
-                "graceful-fs": "^4.2.4",
-                "jest-regex-util": "^27.4.0",
-                "jest-serializer": "^27.4.0",
-                "jest-util": "^27.4.2",
-                "jest-worker": "^27.4.5",
+                "graceful-fs": "^4.2.9",
+                "jest-regex-util": "^27.5.1",
+                "jest-serializer": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-worker": "^27.5.1",
                 "micromatch": "^4.0.4",
                 "walker": "^1.0.7"
             }
         },
         "jest-jasmine2": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.4.5.tgz",
-            "integrity": "sha512-oUnvwhJDj2LhOiUB1kdnJjkx8C5PwgUZQb9urF77mELH9DGR4e2GqpWQKBOYXWs5+uTN9BGDqRz3Aeg5Wts7aw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz",
+            "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==",
             "dev": true,
             "requires": {
-                "@babel/traverse": "^7.1.0",
-                "@jest/environment": "^27.4.4",
-                "@jest/source-map": "^27.4.0",
-                "@jest/test-result": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/environment": "^27.5.1",
+                "@jest/source-map": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "co": "^4.6.0",
-                "expect": "^27.4.2",
+                "expect": "^27.5.1",
                 "is-generator-fn": "^2.0.0",
-                "jest-each": "^27.4.2",
-                "jest-matcher-utils": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-runtime": "^27.4.5",
-                "jest-snapshot": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "pretty-format": "^27.4.2",
+                "jest-each": "^27.5.1",
+                "jest-matcher-utils": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-runtime": "^27.5.1",
+                "jest-snapshot": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "pretty-format": "^27.5.1",
                 "throat": "^6.0.1"
             }
         },
         "jest-leak-detector": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.4.2.tgz",
-            "integrity": "sha512-ml0KvFYZllzPBJWDei3mDzUhyp/M4ubKebX++fPaudpe8OsxUE+m+P6ciVLboQsrzOCWDjE20/eXew9QMx/VGw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz",
+            "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==",
             "dev": true,
             "requires": {
-                "jest-get-type": "^27.4.0",
-                "pretty-format": "^27.4.2"
+                "jest-get-type": "^27.5.1",
+                "pretty-format": "^27.5.1"
             }
         },
         "jest-matcher-utils": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.4.2.tgz",
-            "integrity": "sha512-jyP28er3RRtMv+fmYC/PKG8wvAmfGcSNproVTW2Y0P/OY7/hWUOmsPfxN1jOhM+0u2xU984u2yEagGivz9OBGQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz",
+            "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==",
             "dev": true,
             "requires": {
                 "chalk": "^4.0.0",
-                "jest-diff": "^27.4.2",
-                "jest-get-type": "^27.4.0",
-                "pretty-format": "^27.4.2"
+                "jest-diff": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "pretty-format": "^27.5.1"
             }
         },
         "jest-message-util": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.4.2.tgz",
-            "integrity": "sha512-OMRqRNd9E0DkBLZpFtZkAGYOXl6ZpoMtQJWTAREJKDOFa0M6ptB7L67tp+cszMBkvSgKOhNtQp2Vbcz3ZZKo/w==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz",
+            "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==",
             "dev": true,
             "requires": {
                 "@babel/code-frame": "^7.12.13",
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/stack-utils": "^2.0.0",
                 "chalk": "^4.0.0",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "micromatch": "^4.0.4",
-                "pretty-format": "^27.4.2",
+                "pretty-format": "^27.5.1",
                 "slash": "^3.0.0",
                 "stack-utils": "^2.0.3"
             }
         },
         "jest-mock": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.4.2.tgz",
-            "integrity": "sha512-PDDPuyhoukk20JrQKeofK12hqtSka7mWH0QQuxSNgrdiPsrnYYLS6wbzu/HDlxZRzji5ylLRULeuI/vmZZDrYA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz",
+            "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*"
             }
         },
@@ -8372,201 +7920,194 @@
             "requires": {}
         },
         "jest-regex-util": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.4.0.tgz",
-            "integrity": "sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz",
+            "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==",
             "dev": true
         },
         "jest-resolve": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.4.5.tgz",
-            "integrity": "sha512-xU3z1BuOz/hUhVUL+918KqUgK+skqOuUsAi7A+iwoUldK6/+PW+utK8l8cxIWT9AW7IAhGNXjSAh1UYmjULZZw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz",
+            "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "chalk": "^4.0.0",
-                "graceful-fs": "^4.2.4",
-                "jest-haste-map": "^27.4.5",
+                "graceful-fs": "^4.2.9",
+                "jest-haste-map": "^27.5.1",
                 "jest-pnp-resolver": "^1.2.2",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
+                "jest-util": "^27.5.1",
+                "jest-validate": "^27.5.1",
                 "resolve": "^1.20.0",
                 "resolve.exports": "^1.1.0",
                 "slash": "^3.0.0"
             }
         },
         "jest-resolve-dependencies": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.4.5.tgz",
-            "integrity": "sha512-elEVvkvRK51y037NshtEkEnukMBWvlPzZHiL847OrIljJ8yIsujD2GXRPqDXC4rEVKbcdsy7W0FxoZb4WmEs7w==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz",
+            "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
-                "jest-regex-util": "^27.4.0",
-                "jest-snapshot": "^27.4.5"
+                "@jest/types": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-snapshot": "^27.5.1"
             }
         },
         "jest-runner": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.4.5.tgz",
-            "integrity": "sha512-/irauncTfmY1WkTaRQGRWcyQLzK1g98GYG/8QvIPviHgO1Fqz1JYeEIsSfF+9mc/UTA6S+IIHFgKyvUrtiBIZg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz",
+            "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==",
             "dev": true,
             "requires": {
-                "@jest/console": "^27.4.2",
-                "@jest/environment": "^27.4.4",
-                "@jest/test-result": "^27.4.2",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/console": "^27.5.1",
+                "@jest/environment": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "emittery": "^0.8.1",
-                "exit": "^0.1.2",
-                "graceful-fs": "^4.2.4",
-                "jest-docblock": "^27.4.0",
-                "jest-environment-jsdom": "^27.4.4",
-                "jest-environment-node": "^27.4.4",
-                "jest-haste-map": "^27.4.5",
-                "jest-leak-detector": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-resolve": "^27.4.5",
-                "jest-runtime": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-worker": "^27.4.5",
+                "graceful-fs": "^4.2.9",
+                "jest-docblock": "^27.5.1",
+                "jest-environment-jsdom": "^27.5.1",
+                "jest-environment-node": "^27.5.1",
+                "jest-haste-map": "^27.5.1",
+                "jest-leak-detector": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-runtime": "^27.5.1",
+                "jest-util": "^27.5.1",
+                "jest-worker": "^27.5.1",
                 "source-map-support": "^0.5.6",
                 "throat": "^6.0.1"
             }
         },
         "jest-runtime": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.4.5.tgz",
-            "integrity": "sha512-CIYqwuJQXHQtPd/idgrx4zgJ6iCb6uBjQq1RSAGQrw2S8XifDmoM1Ot8NRd80ooAm+ZNdHVwsktIMGlA1F1FAQ==",
-            "dev": true,
-            "requires": {
-                "@jest/console": "^27.4.2",
-                "@jest/environment": "^27.4.4",
-                "@jest/globals": "^27.4.4",
-                "@jest/source-map": "^27.4.0",
-                "@jest/test-result": "^27.4.2",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
-                "@types/yargs": "^16.0.0",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz",
+            "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==",
+            "dev": true,
+            "requires": {
+                "@jest/environment": "^27.5.1",
+                "@jest/fake-timers": "^27.5.1",
+                "@jest/globals": "^27.5.1",
+                "@jest/source-map": "^27.5.1",
+                "@jest/test-result": "^27.5.1",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "chalk": "^4.0.0",
                 "cjs-module-lexer": "^1.0.0",
                 "collect-v8-coverage": "^1.0.0",
                 "execa": "^5.0.0",
-                "exit": "^0.1.2",
                 "glob": "^7.1.3",
-                "graceful-fs": "^4.2.4",
-                "jest-haste-map": "^27.4.5",
-                "jest-message-util": "^27.4.2",
-                "jest-mock": "^27.4.2",
-                "jest-regex-util": "^27.4.0",
-                "jest-resolve": "^27.4.5",
-                "jest-snapshot": "^27.4.5",
-                "jest-util": "^27.4.2",
-                "jest-validate": "^27.4.2",
+                "graceful-fs": "^4.2.9",
+                "jest-haste-map": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-mock": "^27.5.1",
+                "jest-regex-util": "^27.5.1",
+                "jest-resolve": "^27.5.1",
+                "jest-snapshot": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "slash": "^3.0.0",
-                "strip-bom": "^4.0.0",
-                "yargs": "^16.2.0"
+                "strip-bom": "^4.0.0"
             }
         },
         "jest-serializer": {
-            "version": "27.4.0",
-            "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.4.0.tgz",
-            "integrity": "sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz",
+            "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==",
             "dev": true,
             "requires": {
                 "@types/node": "*",
-                "graceful-fs": "^4.2.4"
+                "graceful-fs": "^4.2.9"
             }
         },
         "jest-snapshot": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.4.5.tgz",
-            "integrity": "sha512-eCi/iM1YJFrJWiT9de4+RpWWWBqsHiYxFG9V9o/n0WXs6GpW4lUt4FAHAgFPTLPqCUVzrMQmSmTZSgQzwqR7IQ==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz",
+            "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==",
             "dev": true,
             "requires": {
                 "@babel/core": "^7.7.2",
                 "@babel/generator": "^7.7.2",
-                "@babel/parser": "^7.7.2",
                 "@babel/plugin-syntax-typescript": "^7.7.2",
                 "@babel/traverse": "^7.7.2",
                 "@babel/types": "^7.0.0",
-                "@jest/transform": "^27.4.5",
-                "@jest/types": "^27.4.2",
+                "@jest/transform": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/babel__traverse": "^7.0.4",
                 "@types/prettier": "^2.1.5",
                 "babel-preset-current-node-syntax": "^1.0.0",
                 "chalk": "^4.0.0",
-                "expect": "^27.4.2",
-                "graceful-fs": "^4.2.4",
-                "jest-diff": "^27.4.2",
-                "jest-get-type": "^27.4.0",
-                "jest-haste-map": "^27.4.5",
-                "jest-matcher-utils": "^27.4.2",
-                "jest-message-util": "^27.4.2",
-                "jest-resolve": "^27.4.5",
-                "jest-util": "^27.4.2",
+                "expect": "^27.5.1",
+                "graceful-fs": "^4.2.9",
+                "jest-diff": "^27.5.1",
+                "jest-get-type": "^27.5.1",
+                "jest-haste-map": "^27.5.1",
+                "jest-matcher-utils": "^27.5.1",
+                "jest-message-util": "^27.5.1",
+                "jest-util": "^27.5.1",
                 "natural-compare": "^1.4.0",
-                "pretty-format": "^27.4.2",
+                "pretty-format": "^27.5.1",
                 "semver": "^7.3.2"
             }
         },
         "jest-util": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.4.2.tgz",
-            "integrity": "sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz",
+            "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "ci-info": "^3.2.0",
-                "graceful-fs": "^4.2.4",
+                "graceful-fs": "^4.2.9",
                 "picomatch": "^2.2.3"
             }
         },
         "jest-validate": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.4.2.tgz",
-            "integrity": "sha512-hWYsSUej+Fs8ZhOm5vhWzwSLmVaPAxRy+Mr+z5MzeaHm9AxUpXdoVMEW4R86y5gOobVfBsMFLk4Rb+QkiEpx1A==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz",
+            "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
+                "@jest/types": "^27.5.1",
                 "camelcase": "^6.2.0",
                 "chalk": "^4.0.0",
-                "jest-get-type": "^27.4.0",
+                "jest-get-type": "^27.5.1",
                 "leven": "^3.1.0",
-                "pretty-format": "^27.4.2"
+                "pretty-format": "^27.5.1"
             },
             "dependencies": {
                 "camelcase": {
-                    "version": "6.2.1",
-                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz",
-                    "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==",
+                    "version": "6.3.0",
+                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+                    "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
                     "dev": true
                 }
             }
         },
         "jest-watcher": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.4.2.tgz",
-            "integrity": "sha512-NJvMVyyBeXfDezhWzUOCOYZrUmkSCiatpjpm+nFUid74OZEHk6aMLrZAukIiFDwdbqp6mTM6Ui1w4oc+8EobQg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz",
+            "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==",
             "dev": true,
             "requires": {
-                "@jest/test-result": "^27.4.2",
-                "@jest/types": "^27.4.2",
+                "@jest/test-result": "^27.5.1",
+                "@jest/types": "^27.5.1",
                 "@types/node": "*",
                 "ansi-escapes": "^4.2.1",
                 "chalk": "^4.0.0",
-                "jest-util": "^27.4.2",
+                "jest-util": "^27.5.1",
                 "string-length": "^4.0.1"
             }
         },
         "jest-worker": {
-            "version": "27.4.5",
-            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz",
-            "integrity": "sha512-f2s8kEdy15cv9r7q4KkzGXvlY0JTcmCbMHZBfSQDwW77REr45IDWwd0lksDFeVHH2jJ5pqb90T77XscrjeGzzg==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+            "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
             "dev": true,
             "requires": {
                 "@types/node": "*",
@@ -8641,6 +8182,12 @@
             "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
             "dev": true
         },
+        "json-parse-even-better-errors": {
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+            "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+            "dev": true
+        },
         "json-schema-traverse": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -8684,6 +8231,12 @@
                 "type-check": "~0.4.0"
             }
         },
+        "lines-and-columns": {
+            "version": "1.2.4",
+            "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+            "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+            "dev": true
+        },
         "locate-path": {
             "version": "5.0.0",
             "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -8805,9 +8358,9 @@
             }
         },
         "minimist": {
-            "version": "1.2.5",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-            "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+            "version": "1.2.6",
+            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+            "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
             "dev": true
         },
         "ms": {
@@ -8828,12 +8381,6 @@
             "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
             "dev": true
         },
-        "node-modules-regexp": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
-            "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=",
-            "dev": true
-        },
         "node-releases": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.0.tgz",
@@ -8934,6 +8481,18 @@
                 "callsites": "^3.0.0"
             }
         },
+        "parse-json": {
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+            "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+            "dev": true,
+            "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "error-ex": "^1.3.1",
+                "json-parse-even-better-errors": "^2.3.0",
+                "lines-and-columns": "^1.1.6"
+            }
+        },
         "parse5": {
             "version": "6.0.1",
             "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
@@ -8983,13 +8542,10 @@
             "dev": true
         },
         "pirates": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz",
-            "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==",
-            "dev": true,
-            "requires": {
-                "node-modules-regexp": "^1.0.0"
-            }
+            "version": "4.0.4",
+            "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz",
+            "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==",
+            "dev": true
         },
         "pkg-dir": {
             "version": "4.2.0",
@@ -9007,18 +8563,17 @@
             "dev": true
         },
         "prettier": {
-            "version": "2.5.1",
-            "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
-            "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+            "version": "2.6.2",
+            "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz",
+            "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==",
             "dev": true
         },
         "pretty-format": {
-            "version": "27.4.2",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.2.tgz",
-            "integrity": "sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==",
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+            "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
             "dev": true,
             "requires": {
-                "@jest/types": "^27.4.2",
                 "ansi-regex": "^5.0.1",
                 "ansi-styles": "^5.0.0",
                 "react-is": "^17.0.1"
@@ -9032,12 +8587,6 @@
                 }
             }
         },
-        "progress": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
-            "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
-            "dev": true
-        },
         "prompts": {
             "version": "2.4.2",
             "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@@ -9085,13 +8634,14 @@
             "dev": true
         },
         "resolve": {
-            "version": "1.20.0",
-            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
-            "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+            "version": "1.22.0",
+            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
+            "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
             "dev": true,
             "requires": {
-                "is-core-module": "^2.2.0",
-                "path-parse": "^1.0.6"
+                "is-core-module": "^2.8.1",
+                "path-parse": "^1.0.7",
+                "supports-preserve-symlinks-flag": "^1.0.0"
             }
         },
         "resolve-cwd": {
@@ -9316,6 +8866,12 @@
                 "supports-color": "^7.0.0"
             }
         },
+        "supports-preserve-symlinks-flag": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+            "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+            "dev": true
+        },
         "symbol-tree": {
             "version": "3.2.4",
             "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -9397,9 +8953,9 @@
             }
         },
         "ts-jest": {
-            "version": "27.1.2",
-            "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.2.tgz",
-            "integrity": "sha512-eSOiJOWq6Hhs6Khzk5wKC5sgWIXgXqOCiIl1+3lfnearu58Hj4QpE5tUhQcA3xtZrELbcvAGCsd6HB8OsaVaTA==",
+            "version": "27.1.4",
+            "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz",
+            "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==",
             "dev": true,
             "requires": {
                 "bs-logger": "0.x",
@@ -9458,9 +9014,9 @@
             }
         },
         "typescript": {
-            "version": "4.5.4",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
-            "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
+            "version": "4.6.3",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+            "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
             "dev": true
         },
         "universalify": {
@@ -9485,9 +9041,9 @@
             "dev": true
         },
         "v8-to-istanbul": {
-            "version": "8.1.0",
-            "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz",
-            "integrity": "sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==",
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz",
+            "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==",
             "dev": true,
             "requires": {
                 "@types/istanbul-lib-coverage": "^2.0.1",
@@ -9607,9 +9163,9 @@
             }
         },
         "ws": {
-            "version": "7.5.6",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz",
-            "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==",
+            "version": "7.5.7",
+            "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
+            "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
             "dev": true,
             "requires": {}
         },
diff --git a/package.json b/package.json
index 3dff11f2e9f3ec6732e53d506b464b0255fa9200..6289eee7b98a3f272018d7f4e8c79b6f77d40ff2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
     "name": "css-select",
-    "version": "4.2.1",
+    "version": "5.1.0",
     "description": "a CSS selector compiler/engine",
     "author": "Felix Boehm <me@feedic.com>",
     "funding": {
@@ -17,30 +17,35 @@
     },
     "main": "lib/index.js",
     "types": "lib/index.d.ts",
+    "module": "lib/esm/index.js",
+    "exports": {
+        "require": "./lib/index.js",
+        "import": "./lib/esm/index.js"
+    },
     "files": [
         "lib"
     ],
     "dependencies": {
         "boolbase": "^1.0.0",
-        "css-what": "^5.1.0",
-        "domhandler": "^4.3.0",
-        "domutils": "^2.8.0",
+        "css-what": "^6.1.0",
+        "domhandler": "^5.0.2",
+        "domutils": "^3.0.1",
         "nth-check": "^2.0.1"
     },
     "devDependencies": {
         "@types/boolbase": "^1.0.1",
-        "@types/jest": "^27.0.3",
-        "@types/node": "^17.0.4",
-        "@typescript-eslint/eslint-plugin": "^5.8.0",
-        "@typescript-eslint/parser": "^5.8.0",
+        "@types/jest": "^27.4.1",
+        "@types/node": "^17.0.29",
+        "@typescript-eslint/eslint-plugin": "^5.21.0",
+        "@typescript-eslint/parser": "^5.21.0",
         "cheerio-soupselect": "^0.1.1",
-        "eslint": "^8.5.0",
-        "eslint-config-prettier": "^8.1.0",
-        "htmlparser2": "^7.2.0",
-        "jest": "^27.4.5",
-        "prettier": "^2.5.1",
-        "ts-jest": "^27.1.2",
-        "typescript": "^4.5.4"
+        "eslint": "^8.14.0",
+        "eslint-config-prettier": "^8.5.0",
+        "htmlparser2": "^8.0.0",
+        "jest": "^27.5.1",
+        "prettier": "^2.6.2",
+        "ts-jest": "^27.1.4",
+        "typescript": "^4.6.3"
     },
     "scripts": {
         "test": "npm run test:jest && npm run lint",
@@ -52,7 +57,9 @@
         "format:es": "npm run lint:es -- --fix",
         "format:prettier": "npm run prettier -- --write",
         "prettier": "prettier '**/*.{ts,md,json,yml}'",
-        "build": "tsc",
+        "build": "npm run build:cjs && npm run build:esm",
+        "build:cjs": "tsc --sourceRoot https://raw.githubusercontent.com/fb55/css-select/$(git rev-parse HEAD)/src/",
+        "build:esm": "npm run build:cjs -- --module esnext --target es2019 --outDir lib/esm && echo '{\"type\":\"module\"}' > lib/esm/package.json",
         "prepare": "npm run build"
     },
     "license": "BSD-2-Clause",
@@ -63,6 +70,10 @@
     "jest": {
         "preset": "ts-jest",
         "testEnvironment": "node",
+        "coverageProvider": "v8",
+        "moduleNameMapper": {
+            "^(.*)\\.js$": "$1"
+        },
         "testMatch": [
             "<rootDir>/test/*.ts"
         ]
diff --git a/src/attributes.ts b/src/attributes.ts
index 8aacc96ab9b8b0fdd4d8f006390d52ccc03b7604..f68ba9e017a89962a58dfaaf2c391a7b907bdee1 100644
--- a/src/attributes.ts
+++ b/src/attributes.ts
@@ -1,5 +1,5 @@
-import { falseFunc } from "boolbase";
-import { CompiledQuery, InternalOptions } from "./types";
+import boolbase from "boolbase";
+import type { CompiledQuery, InternalOptions } from "./types.js";
 import type { AttributeSelector, AttributeAction } from "css-what";
 
 /**
@@ -13,6 +13,72 @@ function escapeRegex(value: string): string {
     return value.replace(reChars, "\\$&");
 }
 
+/**
+ * Attributes that are case-insensitive in HTML.
+ *
+ * @private
+ * @see https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors
+ */
+const caseInsensitiveAttributes = new Set([
+    "accept",
+    "accept-charset",
+    "align",
+    "alink",
+    "axis",
+    "bgcolor",
+    "charset",
+    "checked",
+    "clear",
+    "codetype",
+    "color",
+    "compact",
+    "declare",
+    "defer",
+    "dir",
+    "direction",
+    "disabled",
+    "enctype",
+    "face",
+    "frame",
+    "hreflang",
+    "http-equiv",
+    "lang",
+    "language",
+    "link",
+    "media",
+    "method",
+    "multiple",
+    "nohref",
+    "noresize",
+    "noshade",
+    "nowrap",
+    "readonly",
+    "rel",
+    "rev",
+    "rules",
+    "scope",
+    "scrolling",
+    "selected",
+    "shape",
+    "target",
+    "text",
+    "type",
+    "valign",
+    "valuetype",
+    "vlink",
+]);
+
+function shouldIgnoreCase<Node, ElementNode extends Node>(
+    selector: AttributeSelector,
+    options: InternalOptions<Node, ElementNode>
+): boolean {
+    return typeof selector.ignoreCase === "boolean"
+        ? selector.ignoreCase
+        : selector.ignoreCase === "quirks"
+        ? !!options.quirksMode
+        : !options.xmlMode && caseInsensitiveAttributes.has(selector.name);
+}
+
 /**
  * Attribute selectors
  */
@@ -24,11 +90,12 @@ export const attributeRules: Record<
         options: InternalOptions<Node, ElementNode>
     ) => CompiledQuery<ElementNode>
 > = {
-    equals(next, data, { adapter }) {
+    equals(next, data, options) {
+        const { adapter } = options;
         const { name } = data;
         let { value } = data;
 
-        if (data.ignoreCase) {
+        if (shouldIgnoreCase(data, options)) {
             value = value.toLowerCase();
 
             return (elem) => {
@@ -45,12 +112,13 @@ export const attributeRules: Record<
         return (elem) =>
             adapter.getAttributeValue(elem, name) === value && next(elem);
     },
-    hyphen(next, data, { adapter }) {
+    hyphen(next, data, options) {
+        const { adapter } = options;
         const { name } = data;
         let { value } = data;
         const len = value.length;
 
-        if (data.ignoreCase) {
+        if (shouldIgnoreCase(data, options)) {
             value = value.toLowerCase();
 
             return function hyphenIC(elem) {
@@ -74,14 +142,16 @@ export const attributeRules: Record<
             );
         };
     },
-    element(next, { name, value, ignoreCase }, { adapter }) {
+    element(next, data, options) {
+        const { adapter } = options;
+        const { name, value } = data;
         if (/\s/.test(value)) {
-            return falseFunc;
+            return boolbase.falseFunc;
         }
 
         const regex = new RegExp(
             `(?:^|\\s)${escapeRegex(value)}(?:$|\\s)`,
-            ignoreCase ? "i" : ""
+            shouldIgnoreCase(data, options) ? "i" : ""
         );
 
         return function element(elem) {
@@ -97,16 +167,17 @@ export const attributeRules: Record<
     exists(next, { name }, { adapter }) {
         return (elem) => adapter.hasAttrib(elem, name) && next(elem);
     },
-    start(next, data, { adapter }) {
+    start(next, data, options) {
+        const { adapter } = options;
         const { name } = data;
         let { value } = data;
         const len = value.length;
 
         if (len === 0) {
-            return falseFunc;
+            return boolbase.falseFunc;
         }
 
-        if (data.ignoreCase) {
+        if (shouldIgnoreCase(data, options)) {
             value = value.toLowerCase();
 
             return (elem) => {
@@ -124,16 +195,17 @@ export const attributeRules: Record<
             !!adapter.getAttributeValue(elem, name)?.startsWith(value) &&
             next(elem);
     },
-    end(next, data, { adapter }) {
+    end(next, data, options) {
+        const { adapter } = options;
         const { name } = data;
         let { value } = data;
         const len = -value.length;
 
         if (len === 0) {
-            return falseFunc;
+            return boolbase.falseFunc;
         }
 
-        if (data.ignoreCase) {
+        if (shouldIgnoreCase(data, options)) {
             value = value.toLowerCase();
 
             return (elem) =>
@@ -147,14 +219,15 @@ export const attributeRules: Record<
             !!adapter.getAttributeValue(elem, name)?.endsWith(value) &&
             next(elem);
     },
-    any(next, data, { adapter }) {
+    any(next, data, options) {
+        const { adapter } = options;
         const { name, value } = data;
 
         if (value === "") {
-            return falseFunc;
+            return boolbase.falseFunc;
         }
 
-        if (data.ignoreCase) {
+        if (shouldIgnoreCase(data, options)) {
             const regex = new RegExp(escapeRegex(value), "i");
 
             return function anyIC(elem) {
@@ -172,14 +245,15 @@ export const attributeRules: Record<
             !!adapter.getAttributeValue(elem, name)?.includes(value) &&
             next(elem);
     },
-    not(next, data, { adapter }) {
+    not(next, data, options) {
+        const { adapter } = options;
         const { name } = data;
         let { value } = data;
 
         if (value === "") {
             return (elem) =>
                 !!adapter.getAttributeValue(elem, name) && next(elem);
-        } else if (data.ignoreCase) {
+        } else if (shouldIgnoreCase(data, options)) {
             value = value.toLowerCase();
 
             return (elem) => {
diff --git a/src/compile.ts b/src/compile.ts
index 0974cbac740277f57ac7b03c1ce16001febb2d6c..f7f9ebd32f0785a03f7e54288e5ae4016e025635 100644
--- a/src/compile.ts
+++ b/src/compile.ts
@@ -1,14 +1,16 @@
-import { InternalSelector } from "./types";
-import { parse, Selector } from "css-what";
-import { trueFunc, falseFunc } from "boolbase";
-import sortRules from "./sort";
-import { isTraversal } from "./procedure";
-import { compileGeneralSelector } from "./general";
+import { parse, Selector, SelectorType } from "css-what";
+import boolbase from "boolbase";
+import sortRules, { isTraversal } from "./sort.js";
+import { compileGeneralSelector } from "./general.js";
 import {
     ensureIsTag,
     PLACEHOLDER_ELEMENT,
-} from "./pseudo-selectors/subselects";
-import type { CompiledQuery, InternalOptions } from "./types";
+} from "./pseudo-selectors/subselects.js";
+import type {
+    CompiledQuery,
+    InternalOptions,
+    InternalSelector,
+} from "./types.js";
 
 /**
  * Compiles a selector to an executable function.
@@ -31,28 +33,31 @@ export function compileUnsafe<Node, ElementNode extends Node>(
     options: InternalOptions<Node, ElementNode>,
     context?: Node[] | Node
 ): CompiledQuery<ElementNode> {
-    const token =
-        typeof selector === "string" ? parse(selector, options) : selector;
+    const token = typeof selector === "string" ? parse(selector) : selector;
     return compileToken<Node, ElementNode>(token, options, context);
 }
 
 function includesScopePseudo(t: InternalSelector): boolean {
     return (
-        t.type === "pseudo" &&
+        t.type === SelectorType.Pseudo &&
         (t.name === "scope" ||
             (Array.isArray(t.data) &&
                 t.data.some((data) => data.some(includesScopePseudo))))
     );
 }
 
-const DESCENDANT_TOKEN: Selector = { type: "descendant" };
+const DESCENDANT_TOKEN: Selector = { type: SelectorType.Descendant };
 const FLEXIBLE_DESCENDANT_TOKEN: InternalSelector = {
     type: "_flexibleDescendant",
 };
-const SCOPE_TOKEN: Selector = { type: "pseudo", name: "scope", data: null };
+const SCOPE_TOKEN: Selector = {
+    type: SelectorType.Pseudo,
+    name: "scope",
+    data: null,
+};
 
 /*
- * CSS 4 Spec (Draft): 3.3.1. Absolutizing a Scope-relative Selector
+ * CSS 4 Spec (Draft): 3.4.1. Absolutizing a Relative Selector
  * http://www.w3.org/TR/selectors4/#absolutizing
  */
 function absolutize<Node, ElementNode extends Node>(
@@ -67,7 +72,11 @@ function absolutize<Node, ElementNode extends Node>(
     });
 
     for (const t of token) {
-        if (t.length > 0 && isTraversal(t[0]) && t[0].type !== "descendant") {
+        if (
+            t.length > 0 &&
+            isTraversal(t[0]) &&
+            t[0].type !== SelectorType.Descendant
+        ) {
             // Don't continue in else branch
         } else if (hasContext && !t.some(includesScopePseudo)) {
             t.unshift(DESCENDANT_TOKEN);
@@ -84,8 +93,6 @@ export function compileToken<Node, ElementNode extends Node>(
     options: InternalOptions<Node, ElementNode>,
     context?: Node[] | Node
 ): CompiledQuery<ElementNode> {
-    token = token.filter((t) => t.length > 0);
-
     token.forEach(sortRules);
 
     context = options.context ?? context;
@@ -94,7 +101,14 @@ export function compileToken<Node, ElementNode extends Node>(
     const finalContext =
         context && (Array.isArray(context) ? context : [context]);
 
-    absolutize(token, options, finalContext);
+    // Check if the selector is relative
+    if (options.relativeSelector !== false) {
+        absolutize(token, options, finalContext);
+    } else if (token.some((t) => t.length > 0 && isTraversal(t[0]))) {
+        throw new Error(
+            "Relative selectors are not allowed when the `relativeSelector` option is disabled"
+        );
+    }
 
     let shouldTestNextSiblings = false;
 
@@ -103,13 +117,19 @@ export function compileToken<Node, ElementNode extends Node>(
             if (rules.length >= 2) {
                 const [first, second] = rules;
 
-                if (first.type !== "pseudo" || first.name !== "scope") {
+                if (
+                    first.type !== SelectorType.Pseudo ||
+                    first.name !== "scope"
+                ) {
                     // Ignore
-                } else if (isArrayContext && second.type === "descendant") {
+                } else if (
+                    isArrayContext &&
+                    second.type === SelectorType.Descendant
+                ) {
                     rules[1] = FLEXIBLE_DESCENDANT_TOKEN;
                 } else if (
-                    second.type === "adjacent" ||
-                    second.type === "sibling"
+                    second.type === SelectorType.Adjacent ||
+                    second.type === SelectorType.Sibling
                 ) {
                     shouldTestNextSiblings = true;
                 }
@@ -121,7 +141,7 @@ export function compileToken<Node, ElementNode extends Node>(
                 finalContext
             );
         })
-        .reduce(reduceRules, falseFunc);
+        .reduce(reduceRules, boolbase.falseFunc);
 
     query.shouldTestNextSiblings = shouldTestNextSiblings;
 
@@ -135,8 +155,8 @@ function compileRules<Node, ElementNode extends Node>(
 ): CompiledQuery<ElementNode> {
     return rules.reduce<CompiledQuery<ElementNode>>(
         (previous, rule) =>
-            previous === falseFunc
-                ? falseFunc
+            previous === boolbase.falseFunc
+                ? boolbase.falseFunc
                 : compileGeneralSelector(
                       previous,
                       rule,
@@ -144,7 +164,7 @@ function compileRules<Node, ElementNode extends Node>(
                       context,
                       compileToken
                   ),
-        options.rootFunc ?? trueFunc
+        options.rootFunc ?? boolbase.trueFunc
     );
 }
 
@@ -152,10 +172,10 @@ function reduceRules<Node, ElementNode extends Node>(
     a: CompiledQuery<ElementNode>,
     b: CompiledQuery<ElementNode>
 ): CompiledQuery<ElementNode> {
-    if (b === falseFunc || a === trueFunc) {
+    if (b === boolbase.falseFunc || a === boolbase.trueFunc) {
         return a;
     }
-    if (a === falseFunc || b === trueFunc) {
+    if (a === boolbase.falseFunc || b === boolbase.trueFunc) {
         return b;
     }
 
diff --git a/src/general.ts b/src/general.ts
index 4492dd4a36c3847983df7eb8eef0da87c260f7c7..53b58ecc59c9cb1ccbd3a627f4d520fb2088b766 100644
--- a/src/general.ts
+++ b/src/general.ts
@@ -1,11 +1,24 @@
-import { attributeRules } from "./attributes";
-import { compilePseudoSelector } from "./pseudo-selectors";
+import { attributeRules } from "./attributes.js";
+import { compilePseudoSelector } from "./pseudo-selectors/index.js";
 import type {
+    Adapter,
     CompiledQuery,
     InternalOptions,
     InternalSelector,
     CompileToken,
-} from "./types";
+} from "./types.js";
+import { SelectorType } from "css-what";
+
+function getElementParent<Node, ElementNode extends Node>(
+    node: ElementNode,
+    adapter: Adapter<Node, ElementNode>
+): ElementNode | null {
+    const parent = adapter.getParent(node);
+    if (parent && adapter.isTag(parent)) {
+        return parent;
+    }
+    return null;
+}
 
 /*
  * All available rules
@@ -21,13 +34,27 @@ export function compileGeneralSelector<Node, ElementNode extends Node>(
     const { adapter, equals } = options;
 
     switch (selector.type) {
-        case "pseudo-element":
+        case SelectorType.PseudoElement: {
             throw new Error("Pseudo-elements are not supported by css-select");
+        }
+        case SelectorType.ColumnCombinator: {
+            throw new Error(
+                "Column combinators are not yet supported by css-select"
+            );
+        }
+        case SelectorType.Attribute: {
+            if (selector.namespace != null) {
+                throw new Error(
+                    "Namespaced attributes are not yet supported by css-select"
+                );
+            }
 
-        case "attribute":
+            if (!options.xmlMode || options.lowerCaseAttributeNames) {
+                selector.name = selector.name.toLowerCase();
+            }
             return attributeRules[selector.action](next, selector, options);
-
-        case "pseudo":
+        }
+        case SelectorType.Pseudo: {
             return compilePseudoSelector(
                 next,
                 selector,
@@ -35,15 +62,28 @@ export function compileGeneralSelector<Node, ElementNode extends Node>(
                 context,
                 compileToken
             );
-
+        }
         // Tags
-        case "tag":
+        case SelectorType.Tag: {
+            if (selector.namespace != null) {
+                throw new Error(
+                    "Namespaced tag names are not yet supported by css-select"
+                );
+            }
+
+            let { name } = selector;
+
+            if (!options.xmlMode || options.lowerCaseTags) {
+                name = name.toLowerCase();
+            }
+
             return function tag(elem: ElementNode): boolean {
-                return adapter.getName(elem) === selector.name && next(elem);
+                return adapter.getName(elem) === name && next(elem);
             };
+        }
 
         // Traversal
-        case "descendant":
+        case SelectorType.Descendant: {
             if (
                 options.cacheResults === false ||
                 typeof WeakSet === "undefined"
@@ -51,8 +91,8 @@ export function compileGeneralSelector<Node, ElementNode extends Node>(
                 return function descendant(elem: ElementNode): boolean {
                     let current: ElementNode | null = elem;
 
-                    while ((current = adapter.getParent(current))) {
-                        if (adapter.isTag(current) && next(current)) {
+                    while ((current = getElementParent(current, adapter))) {
+                        if (next(current)) {
                             return true;
                         }
                     }
@@ -62,12 +102,11 @@ export function compileGeneralSelector<Node, ElementNode extends Node>(
             }
 
             // @ts-expect-error `ElementNode` is not extending object
-            // eslint-disable-next-line no-case-declarations
             const isFalseCache = new WeakSet<ElementNode>();
             return function cachedDescendant(elem: ElementNode): boolean {
                 let current: ElementNode | null = elem;
 
-                while ((current = adapter.getParent(current))) {
+                while ((current = getElementParent(current, adapter))) {
                     if (!isFalseCache.has(current)) {
                         if (adapter.isTag(current) && next(current)) {
                             return true;
@@ -78,32 +117,33 @@ export function compileGeneralSelector<Node, ElementNode extends Node>(
 
                 return false;
             };
-        case "_flexibleDescendant":
+        }
+        case "_flexibleDescendant": {
             // Include element itself, only used while querying an array
             return function flexibleDescendant(elem: ElementNode): boolean {
                 let current: ElementNode | null = elem;
 
                 do {
-                    if (adapter.isTag(current) && next(current)) return true;
-                } while ((current = adapter.getParent(current)));
+                    if (next(current)) return true;
+                } while ((current = getElementParent(current, adapter)));
 
                 return false;
             };
-
-        case "parent":
+        }
+        case SelectorType.Parent: {
             return function parent(elem: ElementNode): boolean {
                 return adapter
                     .getChildren(elem)
                     .some((elem) => adapter.isTag(elem) && next(elem));
             };
-
-        case "child":
+        }
+        case SelectorType.Child: {
             return function child(elem: ElementNode): boolean {
                 const parent = adapter.getParent(elem);
                 return parent != null && adapter.isTag(parent) && next(parent);
             };
-
-        case "sibling":
+        }
+        case SelectorType.Sibling: {
             return function sibling(elem: ElementNode): boolean {
                 const siblings = adapter.getSiblings(elem);
 
@@ -117,8 +157,15 @@ export function compileGeneralSelector<Node, ElementNode extends Node>(
 
                 return false;
             };
+        }
+        case SelectorType.Adjacent: {
+            if (adapter.prevElementSibling) {
+                return function adjacent(elem: ElementNode): boolean {
+                    const previous = adapter.prevElementSibling!(elem);
+                    return previous != null && next(previous);
+                };
+            }
 
-        case "adjacent":
             return function adjacent(elem: ElementNode): boolean {
                 const siblings = adapter.getSiblings(elem);
                 let lastElement;
@@ -133,8 +180,15 @@ export function compileGeneralSelector<Node, ElementNode extends Node>(
 
                 return !!lastElement && next(lastElement);
             };
+        }
+        case SelectorType.Universal: {
+            if (selector.namespace != null && selector.namespace !== "*") {
+                throw new Error(
+                    "Namespaced universal selectors are not yet supported by css-select"
+                );
+            }
 
-        case "universal":
             return next;
+        }
     }
 }
diff --git a/src/index.ts b/src/index.ts
index a4f7ccf50808205823e047c61e3495e817f0f8e7..03740daa6ad31b92693c4668b922484a9098587d 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,10 +1,14 @@
 import * as DomUtils from "domutils";
-import { falseFunc } from "boolbase";
+import boolbase from "boolbase";
 import type {
-    Node as DomHandlerNode,
+    AnyNode as DomHandlerNode,
     Element as DomHandlerElement,
 } from "domhandler";
-import { compile as compileRaw, compileUnsafe, compileToken } from "./compile";
+import {
+    compile as compileRaw,
+    compileUnsafe,
+    compileToken,
+} from "./compile.js";
 import type {
     CompiledQuery,
     Options,
@@ -12,8 +16,8 @@ import type {
     Query,
     Adapter,
     Predicate,
-} from "./types";
-import { getNextSiblings } from "./pseudo-selectors/subselects";
+} from "./types.js";
+import { getNextSiblings } from "./pseudo-selectors/subselects.js";
 
 export type { Options };
 
@@ -140,7 +144,7 @@ export const selectAll = getSelectorFunc(
         elems: Node[] | null,
         options: InternalOptions<Node, ElementNode>
     ): ElementNode[] =>
-        query === falseFunc || !elems || elems.length === 0
+        query === boolbase.falseFunc || !elems || elems.length === 0
             ? []
             : options.adapter.findAll(query, elems)
 );
@@ -160,7 +164,7 @@ export const selectOne = getSelectorFunc(
         elems: Node[] | null,
         options: InternalOptions<Node, ElementNode>
     ): ElementNode | null =>
-        query === falseFunc || !elems || elems.length === 0
+        query === boolbase.falseFunc || !elems || elems.length === 0
             ? null
             : options.adapter.findOne(query, elems)
 );
@@ -194,4 +198,5 @@ export function is<Node, ElementNode extends Node>(
 export default selectAll;
 
 // Export filters, pseudos and aliases to allow users to supply their own.
-export { filters, pseudos, aliases } from "./pseudo-selectors";
+/** @deprecated Use the `pseudos` option instead. */
+export { filters, pseudos, aliases } from "./pseudo-selectors/index.js";
diff --git a/src/procedure.ts b/src/procedure.ts
deleted file mode 100644
index a957940e8facedbbd2179d98227ff338bfa8d8c7..0000000000000000000000000000000000000000
--- a/src/procedure.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type { Traversal } from "css-what";
-import type { InternalSelector } from "./types";
-
-export const procedure: Record<InternalSelector["type"], number> = {
-    universal: 50,
-    tag: 30,
-    attribute: 1,
-    pseudo: 0,
-    "pseudo-element": 0, // Here to make TS happy, we don't support this.
-    descendant: -1,
-    child: -1,
-    parent: -1,
-    sibling: -1,
-    adjacent: -1,
-    _flexibleDescendant: -1,
-};
-
-export function isTraversal(t: InternalSelector): t is Traversal {
-    return procedure[t.type] < 0;
-}
diff --git a/src/pseudo-selectors/filters.ts b/src/pseudo-selectors/filters.ts
index e63f1ec29cbc1fc623f474fc1a32d56ce62d2da5..19725cd666ca092ebc45550e65cb9e5e897357a4 100644
--- a/src/pseudo-selectors/filters.ts
+++ b/src/pseudo-selectors/filters.ts
@@ -1,6 +1,6 @@
 import getNCheck from "nth-check";
-import { trueFunc, falseFunc } from "boolbase";
-import type { CompiledQuery, InternalOptions, Adapter } from "../types";
+import boolbase from "boolbase";
+import type { CompiledQuery, InternalOptions, Adapter } from "../types.js";
 
 export type Filter = <Node, ElementNode extends Node>(
     next: CompiledQuery<ElementNode>,
@@ -40,8 +40,8 @@ export const filters: Record<string, Filter> = {
     "nth-child"(next, rule, { adapter, equals }) {
         const func = getNCheck(rule);
 
-        if (func === falseFunc) return falseFunc;
-        if (func === trueFunc) return getChildFunc(next, adapter);
+        if (func === boolbase.falseFunc) return boolbase.falseFunc;
+        if (func === boolbase.trueFunc) return getChildFunc(next, adapter);
 
         return function nthChild(elem) {
             const siblings = adapter.getSiblings(elem);
@@ -60,8 +60,8 @@ export const filters: Record<string, Filter> = {
     "nth-last-child"(next, rule, { adapter, equals }) {
         const func = getNCheck(rule);
 
-        if (func === falseFunc) return falseFunc;
-        if (func === trueFunc) return getChildFunc(next, adapter);
+        if (func === boolbase.falseFunc) return boolbase.falseFunc;
+        if (func === boolbase.trueFunc) return getChildFunc(next, adapter);
 
         return function nthLastChild(elem) {
             const siblings = adapter.getSiblings(elem);
@@ -80,8 +80,8 @@ export const filters: Record<string, Filter> = {
     "nth-of-type"(next, rule, { adapter, equals }) {
         const func = getNCheck(rule);
 
-        if (func === falseFunc) return falseFunc;
-        if (func === trueFunc) return getChildFunc(next, adapter);
+        if (func === boolbase.falseFunc) return boolbase.falseFunc;
+        if (func === boolbase.trueFunc) return getChildFunc(next, adapter);
 
         return function nthOfType(elem) {
             const siblings = adapter.getSiblings(elem);
@@ -104,8 +104,8 @@ export const filters: Record<string, Filter> = {
     "nth-last-of-type"(next, rule, { adapter, equals }) {
         const func = getNCheck(rule);
 
-        if (func === falseFunc) return falseFunc;
-        if (func === trueFunc) return getChildFunc(next, adapter);
+        if (func === boolbase.falseFunc) return boolbase.falseFunc;
+        if (func === boolbase.trueFunc) return getChildFunc(next, adapter);
 
         return function nthLastOfType(elem) {
             const siblings = adapter.getSiblings(elem);
@@ -144,7 +144,7 @@ export const filters: Record<string, Filter> = {
 
         if (!context || context.length === 0) {
             // Equivalent to :root
-            return filters.root(next, rule, options);
+            return filters["root"](next, rule, options);
         }
 
         if (context.length === 1) {
@@ -173,7 +173,7 @@ function dynamicStatePseudo(
         const func = adapter[name];
 
         if (typeof func !== "function") {
-            return falseFunc;
+            return boolbase.falseFunc;
         }
 
         return function active(elem) {
diff --git a/src/pseudo-selectors/index.ts b/src/pseudo-selectors/index.ts
index 57cce4aad20eb7300b54bc8d13f4252b1e4d4217..2b974e35caf76dd703cc03f44b24b7fcb4eb1656 100644
--- a/src/pseudo-selectors/index.ts
+++ b/src/pseudo-selectors/index.ts
@@ -12,13 +12,12 @@
  * of `next()` and your code.
  * Pseudos should be used to implement simple checks.
  */
-import { trueFunc, falseFunc } from "boolbase";
-import type { CompiledQuery, InternalOptions, CompileToken } from "../types";
+import type { CompiledQuery, InternalOptions, CompileToken } from "../types.js";
 import { parse, PseudoSelector } from "css-what";
-import { filters } from "./filters";
-import { pseudos, verifyPseudoArgs } from "./pseudos";
-import { aliases } from "./aliases";
-import { subselects } from "./subselects";
+import { filters } from "./filters.js";
+import { pseudos, verifyPseudoArgs } from "./pseudos.js";
+import { aliases } from "./aliases.js";
+import { subselects } from "./subselects.js";
 
 export { filters, pseudos, aliases };
 
@@ -32,29 +31,44 @@ export function compilePseudoSelector<Node, ElementNode extends Node>(
     const { name, data } = selector;
 
     if (Array.isArray(data)) {
+        if (!(name in subselects)) {
+            throw new Error(`Unknown pseudo-class :${name}(${data})`);
+        }
+
         return subselects[name](next, data, options, context, compileToken);
     }
-    if (name in aliases) {
+
+    const userPseudo = options.pseudos?.[name];
+
+    const stringPseudo =
+        typeof userPseudo === "string" ? userPseudo : aliases[name];
+
+    if (typeof stringPseudo === "string") {
         if (data != null) {
             throw new Error(`Pseudo ${name} doesn't have any arguments`);
         }
 
         // The alias has to be parsed here, to make sure options are respected.
-        const alias = parse(aliases[name], options);
-        return subselects.is(next, alias, options, context, compileToken);
+        const alias = parse(stringPseudo);
+        return subselects["is"](next, alias, options, context, compileToken);
     }
+
+    if (typeof userPseudo === "function") {
+        verifyPseudoArgs(userPseudo, name, data, 1);
+
+        return (elem) => userPseudo(elem, data) && next(elem);
+    }
+
     if (name in filters) {
         return filters[name](next, data as string, options, context);
     }
+
     if (name in pseudos) {
         const pseudo = pseudos[name];
-        verifyPseudoArgs(pseudo, name, data);
+        verifyPseudoArgs(pseudo, name, data, 2);
 
-        return pseudo === falseFunc
-            ? falseFunc
-            : next === trueFunc
-            ? (elem) => pseudo(elem, options, data)
-            : (elem) => pseudo(elem, options, data) && next(elem);
+        return (elem) => pseudo(elem, options, data) && next(elem);
     }
-    throw new Error(`unmatched pseudo-class :${name}`);
+
+    throw new Error(`Unknown pseudo-class :${name}`);
 }
diff --git a/src/pseudo-selectors/pseudos.ts b/src/pseudo-selectors/pseudos.ts
index 65fa2ee5ad9170792917441ea9372bb37706f4c0..ac80304e260e1145713f1a85a64ce7aac2478f5c 100644
--- a/src/pseudo-selectors/pseudos.ts
+++ b/src/pseudo-selectors/pseudos.ts
@@ -1,10 +1,10 @@
-import { PseudoSelector } from "css-what";
-import type { InternalOptions } from "../types";
+import type { PseudoSelector } from "css-what";
+import type { InternalOptions } from "../types.js";
 
 export type Pseudo = <Node, ElementNode extends Node>(
     elem: ElementNode,
     options: InternalOptions<Node, ElementNode>,
-    subselect?: ElementNode | string | null
+    subselect?: string | null
 ) => boolean;
 
 // While filters are precompiled, pseudos get called when they are needed
@@ -18,6 +18,10 @@ export const pseudos: Record<string, Pseudo> = {
     },
 
     "first-child"(elem, { adapter, equals }) {
+        if (adapter.prevElementSibling) {
+            return adapter.prevElementSibling(elem) == null;
+        }
+
         const firstChild = adapter
             .getSiblings(elem)
             .find((elem) => adapter.isTag(elem));
@@ -88,16 +92,17 @@ export const pseudos: Record<string, Pseudo> = {
     },
 };
 
-export function verifyPseudoArgs(
-    func: Pseudo,
+export function verifyPseudoArgs<T extends Array<unknown>>(
+    func: (...args: T) => boolean,
     name: string,
-    subselect: PseudoSelector["data"]
+    subselect: PseudoSelector["data"],
+    argIndex: number
 ): void {
     if (subselect === null) {
-        if (func.length > 2) {
-            throw new Error(`pseudo-selector :${name} requires an argument`);
+        if (func.length > argIndex) {
+            throw new Error(`Pseudo-class :${name} requires an argument`);
         }
-    } else if (func.length === 2) {
-        throw new Error(`pseudo-selector :${name} doesn't have any arguments`);
+    } else if (func.length === argIndex) {
+        throw new Error(`Pseudo-class :${name} doesn't have any arguments`);
     }
 }
diff --git a/src/pseudo-selectors/subselects.ts b/src/pseudo-selectors/subselects.ts
index 9640a120e187f520bb457ae52780bb5aadb42bd2..ce11a45fd3e50169acd12e9971eaf709533319fd 100644
--- a/src/pseudo-selectors/subselects.ts
+++ b/src/pseudo-selectors/subselects.ts
@@ -1,8 +1,12 @@
-import { CompileToken } from "./../types";
 import type { Selector } from "css-what";
-import { trueFunc, falseFunc } from "boolbase";
-import type { CompiledQuery, InternalOptions, Adapter } from "../types";
-import { isTraversal } from "../procedure";
+import boolbase from "boolbase";
+import type {
+    CompiledQuery,
+    InternalOptions,
+    CompileToken,
+    Adapter,
+} from "../types.js";
+import { isTraversal } from "../sort.js";
 
 /** Used as a placeholder for :has. Will be replaced with the actual element. */
 export const PLACEHOLDER_ELEMENT = {};
@@ -11,7 +15,7 @@ export function ensureIsTag<Node, ElementNode extends Node>(
     next: CompiledQuery<ElementNode>,
     adapter: Adapter<Node, ElementNode>
 ): CompiledQuery<Node> {
-    if (next === falseFunc) return falseFunc;
+    if (next === boolbase.falseFunc) return boolbase.falseFunc;
     return (elem: Node) => adapter.isTag(elem) && next(elem);
 }
 
@@ -34,15 +38,30 @@ export function getNextSiblings<Node, ElementNode extends Node>(
     return siblings.slice(elemIndex + 1).filter(adapter.isTag);
 }
 
-const is: Subselect = (next, token, options, context, compileToken) => {
-    const opts = {
+function copyOptions<Node, ElementNode extends Node>(
+    options: InternalOptions<Node, ElementNode>
+): InternalOptions<Node, ElementNode> {
+    // Not copied: context, rootFunc
+    return {
         xmlMode: !!options.xmlMode,
+        lowerCaseAttributeNames: !!options.lowerCaseAttributeNames,
+        lowerCaseTags: !!options.lowerCaseTags,
+        quirksMode: !!options.quirksMode,
+        cacheResults: !!options.cacheResults,
+        pseudos: options.pseudos,
         adapter: options.adapter,
         equals: options.equals,
     };
+}
+
+const is: Subselect = (next, token, options, context, compileToken) => {
+    const func = compileToken(token, copyOptions(options), context);
 
-    const func = compileToken(token, opts, context);
-    return (elem) => func(elem) && next(elem);
+    return func === boolbase.trueFunc
+        ? next
+        : func === boolbase.falseFunc
+        ? boolbase.falseFunc
+        : (elem) => func(elem) && next(elem);
 };
 
 /*
@@ -58,20 +77,13 @@ export const subselects: Record<string, Subselect> = {
     matches: is,
     where: is,
     not(next, token, options, context, compileToken) {
-        const opts = {
-            xmlMode: !!options.xmlMode,
-            adapter: options.adapter,
-            equals: options.equals,
-        };
-
-        const func = compileToken(token, opts, context);
-
-        if (func === falseFunc) return next;
-        if (func === trueFunc) return falseFunc;
+        const func = compileToken(token, copyOptions(options), context);
 
-        return function not(elem) {
-            return !func(elem) && next(elem);
-        };
+        return func === boolbase.falseFunc
+            ? next
+            : func === boolbase.trueFunc
+            ? boolbase.falseFunc
+            : (elem) => !func(elem) && next(elem);
     },
     has<Node, ElementNode extends Node>(
         next: CompiledQuery<ElementNode>,
@@ -81,45 +93,39 @@ export const subselects: Record<string, Subselect> = {
         compileToken: CompileToken<Node, ElementNode>
     ): CompiledQuery<ElementNode> {
         const { adapter } = options;
-        const opts = {
-            xmlMode: !!options.xmlMode,
-            adapter,
-            equals: options.equals,
-        };
-
-        // @ts-expect-error Uses an array as a pointer to the current element (side effects)
-        const context: ElementNode[] | undefined = subselect.some((s) =>
-            s.some(isTraversal)
-        )
-            ? [PLACEHOLDER_ELEMENT]
+
+        const opts = copyOptions(options);
+        opts.relativeSelector = true;
+
+        const context = subselect.some((s) => s.some(isTraversal))
+            ? // Used as a placeholder. Will be replaced with the actual element.
+              ([PLACEHOLDER_ELEMENT] as unknown as ElementNode[])
             : undefined;
 
         const compiled = compileToken(subselect, opts, context);
 
-        if (compiled === falseFunc) return falseFunc;
-        if (compiled === trueFunc) {
-            return (elem) =>
-                adapter.getChildren(elem).some(adapter.isTag) && next(elem);
-        }
+        if (compiled === boolbase.falseFunc) return boolbase.falseFunc;
 
         const hasElement = ensureIsTag(compiled, adapter);
 
-        const { shouldTestNextSiblings = false } = compiled;
+        // If `compiled` is `trueFunc`, we can skip this.
+        if (context && compiled !== boolbase.trueFunc) {
+            /*
+             * `shouldTestNextSiblings` will only be true if the query starts with
+             * a traversal (sibling or adjacent). That means we will always have a context.
+             */
+            const { shouldTestNextSiblings = false } = compiled;
 
-        /*
-         * `shouldTestNextSiblings` will only be true if the query starts with
-         * a traversal (sibling or adjacent). That means we will always have a context.
-         */
-        if (context) {
             return (elem) => {
+                if (!next(elem)) return false;
+
                 context[0] = elem;
                 const childs = adapter.getChildren(elem);
                 const nextElements = shouldTestNextSiblings
                     ? [...childs, ...getNextSiblings(elem, adapter)]
                     : childs;
-                return (
-                    next(elem) && adapter.existsOne(hasElement, nextElements)
-                );
+
+                return adapter.existsOne(hasElement, nextElements);
             };
         }
 
diff --git a/src/sort.ts b/src/sort.ts
index 3a1dfa87e1136a1d31e1c5b61852f70e82825143..d5f13d323e63fca713b613aa0633d1cbeb54ad94 100644
--- a/src/sort.ts
+++ b/src/sort.ts
@@ -1,17 +1,25 @@
-import type { InternalSelector } from "./types";
-import type { AttributeAction } from "css-what";
-import { procedure } from "./procedure";
+import type { InternalSelector } from "./types.js";
+import { AttributeAction, SelectorType, type Traversal } from "css-what";
 
-const attributes: Record<AttributeAction, number> = {
-    exists: 10,
-    equals: 8,
-    not: 7,
-    start: 6,
-    end: 6,
-    any: 5,
-    hyphen: 4,
-    element: 4,
-};
+const procedure = new Map<InternalSelector["type"], number>([
+    [SelectorType.Universal, 50],
+    [SelectorType.Tag, 30],
+    [SelectorType.Attribute, 1],
+    [SelectorType.Pseudo, 0],
+]);
+
+export function isTraversal(token: InternalSelector): token is Traversal {
+    return !procedure.has(token.type);
+}
+
+const attributes = new Map<AttributeAction, number>([
+    [AttributeAction.Exists, 10],
+    [AttributeAction.Equals, 8],
+    [AttributeAction.Not, 7],
+    [AttributeAction.Start, 6],
+    [AttributeAction.End, 6],
+    [AttributeAction.Any, 5],
+]);
 
 /**
  * Sort the parts of the passed selector,
@@ -38,12 +46,12 @@ export default function sortByProcedure(arr: InternalSelector[]): void {
 }
 
 function getProcedure(token: InternalSelector): number {
-    let proc = procedure[token.type];
+    let proc = procedure.get(token.type) ?? -1;
 
-    if (token.type === "attribute") {
-        proc = attributes[token.action];
+    if (token.type === SelectorType.Attribute) {
+        proc = attributes.get(token.action) ?? 4;
 
-        if (proc === attributes.equals && token.name === "id") {
+        if (token.action === AttributeAction.Equals && token.name === "id") {
             // Prefer ID selectors (eg. #ID)
             proc = 9;
         }
@@ -55,29 +63,23 @@ function getProcedure(token: InternalSelector): number {
              */
             proc >>= 1;
         }
-    } else if (token.type === "pseudo") {
+    } else if (token.type === SelectorType.Pseudo) {
         if (!token.data) {
             proc = 3;
         } else if (token.name === "has" || token.name === "contains") {
             proc = 0; // Expensive in any case
         } else if (Array.isArray(token.data)) {
-            // "matches" and "not"
-            proc = 0;
+            // Eg. :matches, :not
+            proc = Math.min(
+                ...token.data.map((d) => Math.min(...d.map(getProcedure)))
+            );
 
-            for (let i = 0; i < token.data.length; i++) {
-                // TODO better handling of complex selectors
-                if (token.data[i].length !== 1) continue;
-                const cur = getProcedure(token.data[i][0]);
-                // Avoid executing :has or :contains
-                if (cur === 0) {
-                    proc = 0;
-                    break;
-                }
-                if (cur > proc) proc = cur;
+            // If we have traversals, try to avoid executing this selector
+            if (proc < 0) {
+                proc = 0;
             }
-            if (token.data.length > 1 && proc > 0) proc -= 1;
         } else {
-            proc = 1;
+            proc = 2;
         }
     }
     return proc;
diff --git a/src/types.ts b/src/types.ts
index 9cb2a7902c76e8b3a730e7555b1a7b863912bad2..a0d58a73e6c521ae2943999eacd465d31150b43e 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -32,7 +32,7 @@ export interface Adapter<Node, ElementNode extends Node> {
     /**
      * Get the parent of the node
      */
-    getParent: (node: ElementNode) => ElementNode | null;
+    getParent: (node: ElementNode) => Node | null;
 
     /**
      * Get the siblings of the node. Note that unlike jQuery's `siblings` method,
@@ -40,6 +40,11 @@ export interface Adapter<Node, ElementNode extends Node> {
      */
     getSiblings: (node: Node) => Node[];
 
+    /**
+     * Returns the previous element sibling of a node.
+     */
+    prevElementSibling?: (node: Node) => ElementNode | null;
+
     /**
      * Get the text content of the node, and its children if it has any.
      */
@@ -102,6 +107,40 @@ export interface Options<Node, ElementNode extends Node> {
      * @default false
      */
     xmlMode?: boolean;
+    /**
+     * Lower-case attribute names.
+     *
+     * @default !xmlMode
+     */
+    lowerCaseAttributeNames?: boolean;
+    /**
+     * Lower-case tag names.
+     *
+     * @default !xmlMode
+     */
+    lowerCaseTags?: boolean;
+    /**
+     * Is the document in quirks mode?
+     *
+     * This will lead to .className and #id being case-insensitive.
+     *
+     * @default false
+     */
+    quirksMode?: boolean;
+    /**
+     * Pseudo-classes that override the default ones.
+     *
+     * Maps from names to either strings of functions.
+     * - A string value is a selector that the element must match to be selected.
+     * - A function is called with the element as its first argument, and optional
+     *  parameters second. If it returns true, the element is selected.
+     */
+    pseudos?:
+        | Record<
+              string,
+              string | ((elem: ElementNode, value?: string | null) => boolean)
+          >
+        | undefined;
     /**
      * The last function in the stack, will be called with the last element
      * that's looked at.
@@ -114,9 +153,23 @@ export interface Options<Node, ElementNode extends Node> {
     adapter?: Adapter<Node, ElementNode>;
     /**
      * The context of the current query. Used to limit the scope of searches.
-     * Can be matched directly using the `:scope` pseudo-selector.
+     * Can be matched directly using the `:scope` pseudo-class.
      */
     context?: Node | Node[];
+    /**
+     * Indicates whether to consider the selector as a relative selector.
+     *
+     * Relative selectors that don't include a `:scope` pseudo-class behave
+     * as if they have a `:scope ` prefix (a `:scope` pseudo-class, followed by
+     * a descendant selector).
+     *
+     * If relative selectors are disabled, selectors starting with a traversal
+     * will lead to an error.
+     *
+     * @default true
+     * @see {@link https://www.w3.org/TR/selectors-4/#relative}
+     */
+    relativeSelector?: boolean;
     /**
      * Allow css-select to cache results for some selectors, sometimes greatly
      * improving querying performance. Disable this if your document can
diff --git a/test/api.ts b/test/api.ts
index 23f7603e3322b89b1935725efc6b8d82aa2f6a59..194486a08661098a8009be7b34eb4c505ef6974e 100644
--- a/test/api.ts
+++ b/test/api.ts
@@ -1,13 +1,18 @@
 import * as CSSselect from "../src";
 import { parseDOM, parseDocument } from "htmlparser2";
-import { trueFunc, falseFunc } from "boolbase";
-import type { Element } from "domhandler";
+import boolbase from "boolbase";
+import * as DomUtils from "domutils";
+import type { AnyNode, Element } from "domhandler";
+import { SelectorType, AttributeAction } from "css-what";
+import type { Adapter } from "../src/types.js";
 
 const [dom] = parseDOM("<div id=foo><p>foo</p></div>") as Element[];
 const [xmlDom] = parseDOM("<DiV id=foo><P>foo</P></DiV>", {
     xmlMode: true,
 }) as Element[];
 
+const notYet = "not yet supported by css-select";
+
 describe("API", () => {
     describe("removes duplicates", () => {
         it("between identical trees", () => {
@@ -27,9 +32,9 @@ describe("API", () => {
 
     describe("can be queried with more than a selector", () => {
         it("function in `is`", () => {
-            expect(CSSselect.is(dom, (elem) => elem.attribs.id === "foo")).toBe(
-                true
-            );
+            expect(
+                CSSselect.is(dom, (elem) => elem.attribs["id"] === "foo")
+            ).toBe(true);
         });
 
         it("parsed selector in `is`", () => {
@@ -37,8 +42,8 @@ describe("API", () => {
                 CSSselect.is(dom, [
                     [
                         {
-                            type: "attribute",
-                            action: "equals",
+                            type: SelectorType.Attribute,
+                            action: AttributeAction.Equals,
                             ignoreCase: false,
                             name: "id",
                             namespace: null,
@@ -66,13 +71,36 @@ describe("API", () => {
             ) as Element[];
             const a = CSSselect.selectAll(".foo:has(+.bar)", dom);
             expect(a).toHaveLength(1);
-            expect(a[0]).toStrictEqual(dom.children[0] as Element);
+            expect(a[0]).toStrictEqual(dom.children[0]);
         });
 
         it("should accept document root nodes", () => {
             const doc = parseDocument("<div id=foo><p>foo</p></div>");
             expect(CSSselect.selectAll(":contains(foo)", doc)).toHaveLength(2);
         });
+
+        it("should support scoped selections relative to the root (#709)", () => {
+            const doc = parseDocument(`
+                <div class="parent">
+                    <div class="one"><p class="p1"></p></div>
+                    <div class="two"><p class="p2"></p></div>
+                    <div class="three"><p class="p3"></p></div>
+                </div>`);
+
+            const two = CSSselect.selectOne(".two", doc);
+            expect(
+                CSSselect.selectOne(".parent .two .p2", two, {
+                    relativeSelector: false,
+                })
+            ).toMatchObject({
+                attribs: { class: "p2" },
+            });
+            expect(
+                CSSselect.selectOne(".parent .two .p3", two, {
+                    relativeSelector: false,
+                })
+            ).toBeNull();
+        });
     });
 
     describe("errors", () => {
@@ -80,6 +108,35 @@ describe("API", () => {
             expect(() => CSSselect.compile("::after")).toThrow("not supported");
         });
 
+        it("should throw an error if encountering a traversal-first selector with relative selectors disabled", () =>
+            expect(() =>
+                CSSselect.compile("> p", { relativeSelector: false })
+            ).toThrow(
+                "Relative selectors are not allowed when the `relativeSelector` option is disabled"
+            ));
+
+        it("should throw with a column combinator", () => {
+            expect(() => CSSselect.compile("foo || bar")).toThrow(notYet);
+        });
+
+        it("should throw with attribute namespace", () => {
+            expect(() => CSSselect.compile("[foo|bar]")).toThrow(notYet);
+            expect(() => CSSselect.compile("[|bar]")).not.toThrow();
+            expect(() => CSSselect.compile("[*|bar]")).toThrow(notYet);
+        });
+
+        it("should throw with tag namespace", () => {
+            expect(() => CSSselect.compile("foo|bar")).toThrow(notYet);
+            expect(() => CSSselect.compile("|bar")).toThrow(notYet);
+            expect(() => CSSselect.compile("*|bar")).toThrow(notYet);
+        });
+
+        it("should throw with universal selector", () => {
+            expect(() => CSSselect.compile("foo|*")).toThrow(notYet);
+            expect(() => CSSselect.compile("|*")).toThrow(notYet);
+            expect(() => CSSselect.compile("*|*")).not.toThrow();
+        });
+
         it("should throw if parameter is supplied for pseudo", () => {
             expect(() => CSSselect.compile(":any-link(test)")).toThrow(
                 "doesn't have any arguments"
@@ -91,44 +148,85 @@ describe("API", () => {
         });
 
         it("should throw if no parameter is supplied for pseudo", () => {
-            CSSselect.pseudos.foovalue = (elem, { adapter }, subselect) =>
+            CSSselect.pseudos["foovalue"] = (elem, { adapter }, subselect) =>
                 adapter.getAttributeValue(elem, "foo") === subselect;
 
             expect(() => CSSselect.compile(":foovalue")).toThrow(
                 "requires an argument"
             );
 
-            delete CSSselect.pseudos.foovalue;
+            delete CSSselect.pseudos["foovalue"];
         });
+
+        it("should throw if parameter is supplied for user-provided pseudo", () =>
+            expect(() =>
+                CSSselect.compile(":foovalue(boo)", {
+                    pseudos: { foovalue: "tag" },
+                })
+            ).toThrow("doesn't have any arguments"));
+
+        it("should throw if no parameter is supplied for user-provided pseudo", () =>
+            expect(() =>
+                CSSselect.compile(":foovalue", {
+                    pseudos: {
+                        foovalue(_el, data) {
+                            return data != null;
+                        },
+                    },
+                })
+            ).toThrow("requires an argument"));
     });
 
     describe("unsatisfiable and universally valid selectors", () => {
         it("in :not", () => {
-            let func = CSSselect._compileUnsafe(":not(*)");
-            expect(func).toBe(falseFunc);
-            func = CSSselect._compileUnsafe(":not(:nth-child(-1n-1))");
-            expect(func).toBe(trueFunc);
-            func = CSSselect._compileUnsafe(":not(:not(:not(*)))");
-            expect(func).toBe(falseFunc);
+            expect(CSSselect._compileUnsafe(":not(*)")).toBe(
+                boolbase.falseFunc
+            );
+            expect(CSSselect._compileUnsafe(":not(:nth-child(-1n-1))")).toBe(
+                boolbase.trueFunc
+            );
+            expect(CSSselect._compileUnsafe(":not(:not(:not(*)))")).toBe(
+                boolbase.falseFunc
+            );
         });
 
         it("in :has", () => {
             const matches = CSSselect.selectAll(":has(*)", [dom]);
             expect(matches).toHaveLength(1);
             expect(matches[0]).toBe(dom);
-            const func = CSSselect._compileUnsafe(":has(:nth-child(-1n-1))");
-            expect(func).toBe(falseFunc);
-        });
 
-        it("should skip unsatisfiable", () => {
-            const func = CSSselect._compileUnsafe("* :not(*) foo");
-            expect(func).toBe(falseFunc);
+            expect(CSSselect._compileUnsafe(":has(:nth-child(-1n-1))")).toBe(
+                boolbase.falseFunc
+            );
+
+            const matches2 = CSSselect.selectAll(
+                "p:has(+ *)",
+                parseDOM("<p><p>")
+            );
+            expect(matches2).toHaveLength(1);
+            expect(matches2[0]).toHaveProperty("tagName", "p");
         });
 
-        it("should promote universally valid", () => {
-            const func = CSSselect._compileUnsafe("*, foo");
-            expect(func).toBe(trueFunc);
+        it("in :is", () => {
+            expect(CSSselect._compileUnsafe(":is(*)")).toBe(boolbase.trueFunc);
+            expect(CSSselect._compileUnsafe(":is(:nth-child(-1n-1))")).toBe(
+                boolbase.falseFunc
+            );
+            expect(CSSselect._compileUnsafe(":is(:not(:not(*)))")).toBe(
+                boolbase.trueFunc
+            );
+            expect(CSSselect._compileUnsafe(":is(*, :scope)")).toBe(
+                boolbase.trueFunc
+            );
         });
+
+        it("should skip unsatisfiable", () =>
+            expect(CSSselect._compileUnsafe("* :not(*) foo")).toBe(
+                boolbase.falseFunc
+            ));
+
+        it("should promote universally valid", () =>
+            expect(CSSselect._compileUnsafe("*, foo")).toBe(boolbase.trueFunc));
     });
 
     describe(":matches", () => {
@@ -217,7 +315,7 @@ describe("API", () => {
             expect(CSSselect.selectOne(":contains(foo)", [dom])).toBe(dom);
         });
         it("should take shortcuts when applicable", () => {
-            let match = CSSselect.selectOne(falseFunc, {
+            let match = CSSselect.selectOne(boolbase.falseFunc, {
                 get length() {
                     throw new Error("Did not take shortcut");
                 },
@@ -270,7 +368,7 @@ describe("API", () => {
             const query = CSSselect.compile("#bar p");
 
             expect(CSSselect.selectAll(query, [dom])).toHaveLength(0);
-            dom.attribs.id = "bar";
+            dom.attribs["id"] = "bar";
             // The query should be cached and the changed attribute should be ignored.
             expect(CSSselect.selectAll(query, [dom])).toHaveLength(0);
         });
@@ -282,9 +380,53 @@ describe("API", () => {
             const query = CSSselect.compile("#bar p", { cacheResults: false });
 
             expect(CSSselect.selectAll(query, [dom])).toHaveLength(0);
-            dom.attribs.id = "bar";
+            dom.attribs["id"] = "bar";
             // The query should not be cached, the changed attribute should be picked up.
             expect(CSSselect.selectAll(query, [dom])).toHaveLength(1);
         });
+
+        it("should pass options to sub-selectors", () => {
+            expect(
+                CSSselect.selectAll("div:is(DiV#FOO):not([ID]):foo", [dom], {
+                    xmlMode: true,
+                    lowerCaseTags: true,
+                    quirksMode: true,
+                    pseudos: { foo: "#fOO" },
+                })
+            ).toHaveLength(1);
+        });
+    });
+
+    describe("optional adapter methods", () => {
+        it("should support prevElementSibling", () => {
+            const adapter: Adapter<AnyNode, Element> = { ...DomUtils };
+            delete adapter.prevElementSibling;
+
+            const dom = parseDOM(
+                `${"<p>foo".repeat(10)}<div>bar</div>`
+            ) as Element[];
+
+            expect(
+                CSSselect.selectAll("p + div", dom, { adapter })
+            ).toStrictEqual(CSSselect.selectAll("p + div", dom));
+        });
+
+        it("should support isHovered", () => {
+            const dom = parseDOM(`${"<p>foo".repeat(10)}`) as Element[];
+
+            const adapter = {
+                ...DomUtils,
+                isHovered: (el: Element) => el === dom[dom.length - 1],
+            };
+
+            const selection = CSSselect.selectAll("p:hover", dom, { adapter });
+            expect(selection).toHaveLength(1);
+            expect(selection[0]).toBe(dom[dom.length - 1]);
+        });
+
+        it("should not match any elements if `isHovered` is not defined", () => {
+            const dom = parseDOM(`${"<p>foo".repeat(10)}`);
+            expect(CSSselect.selectAll("p:hover", dom)).toHaveLength(0);
+        });
     });
 });
diff --git a/test/attributes.ts b/test/attributes.ts
index 8df6505c9e5557ca071ed40951a39c566166bb30..1dc940d6a8986d820ce21b6e182399623e138563 100644
--- a/test/attributes.ts
+++ b/test/attributes.ts
@@ -1,6 +1,6 @@
 import * as CSSselect from "../src";
 import { parseDocument } from "htmlparser2";
-import { falseFunc } from "boolbase";
+import boolbase from "boolbase";
 import type { Element } from "domhandler";
 
 const dom = parseDocument(
@@ -86,16 +86,20 @@ describe("Attributes", () => {
     describe("no matches", () => {
         it("should for ~=", () => {
             expect(CSSselect._compileUnsafe("[foo~='baz bar']")).toBe(
-                falseFunc
+                boolbase.falseFunc
             );
         });
 
         it("should for $=", () => {
-            expect(CSSselect._compileUnsafe("[foo$='']")).toBe(falseFunc);
+            expect(CSSselect._compileUnsafe("[foo$='']")).toBe(
+                boolbase.falseFunc
+            );
         });
 
         it("should for *=", () => {
-            expect(CSSselect._compileUnsafe("[foo*='']")).toBe(falseFunc);
+            expect(CSSselect._compileUnsafe("[foo*='']")).toBe(
+                boolbase.falseFunc
+            );
         });
     });
 });
diff --git a/test/nwmatcher.ts b/test/nwmatcher.ts
index f4214378f92fcd0865149738b3402c25032876d8..119e266e3d5b9867d2243e572c6d7a359026f7d2 100644
--- a/test/nwmatcher.ts
+++ b/test/nwmatcher.ts
@@ -19,9 +19,7 @@ function getByIds(...args: string[]): Element[] {
 }
 
 function getById(id: string): Element {
-    const elem = DomUtils.getElementById(id, document);
-    if (!elem) throw new Error(`Did not find element with ID ${id}`);
-    return elem;
+    return document.getElementById(id);
 }
 
 // NWMatcher methods
@@ -29,6 +27,11 @@ const select = (query: string, doc: Node[] | Node = document): Node[] =>
     CSSselect.selectAll(query, doc);
 
 describe("NWMatcher", () => {
+    // Test whether our helper above throws
+    it("should throw when getting an element by an invalid ID", () => {
+        expect(() => getById("foo")).toThrow();
+    });
+
     describe("Basic Selectors", () => {
         it("*", () => {
             // Universal selector
@@ -140,12 +143,12 @@ describe("NWMatcher", () => {
             );
         });
 
-        it.skip("E[foo] with namespaced attributes", () => {
-            expect(select("[xml:lang]")).toStrictEqual([
+        it("E[foo] with namespaced attributes", () => {
+            expect(select("[xml\\:lang]")).toStrictEqual([
                 document.documentElement,
                 getById("item_3"),
             ]);
-            expect(select("*[xml:lang]")).toStrictEqual([
+            expect(select("*[xml\\:lang]")).toStrictEqual([
                 document.documentElement,
                 getById("item_3"),
             ]);
@@ -575,10 +578,10 @@ describe("NWMatcher", () => {
             );
         });
 
-        it.skip("Multiple Selectors with lang", () => {
+        it("Multiple Selectors with lang", () => {
             // The next two assertions should return document-ordered lists of matching elements --Diego Perini
             expect(
-                select('#list, .first,*[xml:lang="es-us"] , #troubleForm')
+                select('#list, .first,*[xml\\:lang="es-us"] , #troubleForm')
             ).toStrictEqual(
                 getByIds(
                     "p",
@@ -590,7 +593,7 @@ describe("NWMatcher", () => {
                 )
             );
             expect(
-                select('#list, .first, *[xml:lang="es-us"], #troubleForm')
+                select('#list, .first, *[xml\\:lang="es-us"], #troubleForm')
             ).toStrictEqual(
                 getByIds(
                     "p",
diff --git a/test/icontains.ts b/test/pseudo-classes.ts
similarity index 64%
rename from test/icontains.ts
rename to test/pseudo-classes.ts
index f94e568fca7d19e9deab0d6d30e01b5a70a87621..ce0aa6c5a7af2fd1fad80b2ae1cd1c16b5126093 100644
--- a/test/icontains.ts
+++ b/test/pseudo-classes.ts
@@ -1,12 +1,13 @@
 import * as CSSselect from "../src";
-import { parseDOM } from "htmlparser2";
-import type { Element } from "domhandler";
+import { DomUtils, parseDOM } from "htmlparser2";
+import type { AnyNode, Element } from "domhandler";
+import type { Adapter } from "../src/types.js";
 
 const dom = parseDOM(
     "<div><p>In the end, it doesn't really Matter.</p><div>Indeed-that's a delicate matter.</div>"
 ) as Element[];
 
-describe("icontains", () => {
+describe(":icontains", () => {
     describe("ignore case", () => {
         it("should match full string", () => {
             let matches = CSSselect.selectAll(
@@ -14,43 +15,31 @@ describe("icontains", () => {
                 dom
             );
             expect(matches).toHaveLength(2);
-            expect(matches).toStrictEqual([
-                dom[0],
-                dom[0].children[1],
-            ] as Element[]);
+            expect(matches).toStrictEqual([dom[0], dom[0].children[1]]);
             matches = CSSselect.selectAll(
                 ":icontains(inDeeD-THAT's a DELICATE matteR.)",
                 dom
             );
             expect(matches).toHaveLength(2);
-            expect(matches).toStrictEqual([
-                dom[0],
-                dom[0].children[1],
-            ] as Element[]);
+            expect(matches).toStrictEqual([dom[0], dom[0].children[1]]);
         });
 
         it("should match substring", () => {
             let matches = CSSselect.selectAll(":icontains(indeed)", dom);
             expect(matches).toHaveLength(2);
-            expect(matches).toStrictEqual([
-                dom[0],
-                dom[0].children[1],
-            ] as Element[]);
+            expect(matches).toStrictEqual([dom[0], dom[0].children[1]]);
             matches = CSSselect.selectAll(":icontains(inDeeD)", dom);
             expect(matches).toHaveLength(2);
-            expect(matches).toStrictEqual([
-                dom[0],
-                dom[0].children[1],
-            ] as Element[]);
+            expect(matches).toStrictEqual([dom[0], dom[0].children[1]]);
         });
 
         it("should match specific element", () => {
             let matches = CSSselect.selectAll("p:icontains(matter)", dom);
             expect(matches).toHaveLength(1);
-            expect(matches).toStrictEqual([dom[0].children[0] as Element]);
+            expect(matches).toStrictEqual([dom[0].children[0]]);
             matches = CSSselect.selectAll("p:icontains(mATter)", dom);
             expect(matches).toHaveLength(1);
-            expect(matches).toStrictEqual([dom[0].children[0] as Element]);
+            expect(matches).toStrictEqual([dom[0].children[0]]);
         });
 
         it("should match multiple elements", () => {
@@ -60,14 +49,14 @@ describe("icontains", () => {
                 dom[0],
                 dom[0].children[0],
                 dom[0].children[1],
-            ] as Element[]);
+            ]);
             matches = CSSselect.selectAll(":icontains(mATter)", dom);
             expect(matches).toHaveLength(3);
             expect(matches).toStrictEqual([
                 dom[0],
                 dom[0].children[0],
                 dom[0].children[1],
-            ] as Element[]);
+            ]);
         });
 
         it("should match empty string", () => {
@@ -77,7 +66,7 @@ describe("icontains", () => {
                 dom[0],
                 dom[0].children[0],
                 dom[0].children[1],
-            ] as Element[]);
+            ]);
         });
 
         it("should match quoted string", () => {
@@ -87,13 +76,13 @@ describe("icontains", () => {
                 dom[0],
                 dom[0].children[0],
                 dom[0].children[1],
-            ] as Element[]);
+            ]);
             matches = CSSselect.selectAll("p:icontains('matter')", dom);
             expect(matches).toHaveLength(1);
-            expect(matches).toStrictEqual([dom[0].children[0] as Element]);
+            expect(matches).toStrictEqual([dom[0].children[0]]);
             matches = CSSselect.selectAll('p:icontains("matter")', dom);
             expect(matches).toHaveLength(1);
-            expect(matches).toStrictEqual([dom[0].children[0] as Element]);
+            expect(matches).toStrictEqual([dom[0].children[0]]);
         });
 
         it("should match whitespace", () => {
@@ -103,14 +92,14 @@ describe("icontains", () => {
                 dom[0],
                 dom[0].children[0],
                 dom[0].children[1],
-            ] as Element[]);
+            ]);
             matches = CSSselect.selectAll(":icontains( mATter)", dom);
             expect(matches).toHaveLength(3);
             expect(matches).toStrictEqual([
                 dom[0],
                 dom[0].children[0],
                 dom[0].children[1],
-            ] as Element[]);
+            ]);
         });
     });
 
@@ -121,3 +110,36 @@ describe("icontains", () => {
         });
     });
 });
+
+describe("unmatched", () => {
+    it("should throw on unknown pseudo-class (#741)", () => {
+        expect(() => CSSselect.selectAll(":unmatched(foo)", dom)).toThrow(
+            "Unknown pseudo-class :unmatched"
+        );
+
+        expect(() => CSSselect.selectAll(":unmatched(foo)", dom)).toThrow(
+            "Unknown pseudo-class :unmatched"
+        );
+
+        expect(() => CSSselect.selectAll(":host-context(foo)", dom)).toThrow(
+            "Unknown pseudo-class :host-context"
+        );
+    });
+});
+
+describe(":first-child", () => {
+    it("should match", () => {
+        const matches = CSSselect.selectAll(":first-child", dom);
+        expect(matches).toHaveLength(2);
+        expect(matches).toStrictEqual([dom[0], dom[0].children[0]]);
+    });
+
+    it("should work without `prevElementSibling`", () => {
+        const adapter: Adapter<AnyNode, Element> = { ...DomUtils };
+        delete adapter.prevElementSibling;
+
+        const matches = CSSselect.selectAll(":first-child", dom, { adapter });
+        expect(matches).toHaveLength(2);
+        expect(matches).toStrictEqual([dom[0], dom[0].children[0]]);
+    });
+});
diff --git a/test/qwery.ts b/test/qwery.ts
index f0e2cd4a68245190e50213bbf65deff1c9a75979..9179942d003bc0cccec705f4f1bf381e80644c01 100644
--- a/test/qwery.ts
+++ b/test/qwery.ts
@@ -2,12 +2,21 @@ import * as helper from "./tools/helper";
 const document = helper.getDocument("qwery.html");
 import * as CSSselect from "../src";
 import * as DomUtils from "domutils";
-import type { Element } from "domhandler";
+import type { AnyNode, Element } from "domhandler";
 import { parseDOM } from "htmlparser2";
 
 const location = { hash: "" };
-CSSselect.pseudos.target = (elem, { adapter }) =>
-    adapter.getAttributeValue(elem, "id") === location.hash.substr(1);
+const options = {
+    pseudos: {
+        target: (elem: Element) =>
+            DomUtils.getAttributeValue(elem, "id") === location.hash.substr(1),
+        humanoid: ":matches(li,ol):contains(human)",
+    },
+};
+
+function selectAll(selector: string, context: AnyNode | AnyNode[] = document) {
+    return CSSselect.selectAll<AnyNode, Element>(selector, context, options);
+}
 
 // ---
 
@@ -15,9 +24,6 @@ CSSselect.pseudos.target = (elem, { adapter }) =>
  * Adapted from https://github.com/ded/qwery/blob/master/tests/tests.js
  */
 
-CSSselect.pseudos.humanoid = (e) =>
-    CSSselect.is(e, ":matches(li,ol):contains(human)");
-
 const frag = parseDOM(
     '<root><div class="d i v">' +
         '<p id="oooo"><em></em><em id="emem"></em></p>' +
@@ -39,154 +45,87 @@ const doc = parseDOM(
         '<div id="lonelyHsoob"></div></root>'
 );
 
-const el = DomUtils.getElementById("attr-child-boosh", document);
-
-if (!el) throw new Error("Couldn't find element");
+const el = document.getElementById("attr-child-boosh");
 
-// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-const pseudos = DomUtils.getElementById("pseudos", document)!.children.filter(
-    DomUtils.isTag
-);
+const pseudos = document
+    .getElementById("pseudos")
+    .children.filter(DomUtils.isTag);
 
 describe("qwery", () => {
     describe("Contexts", () => {
         it("should be able to pass optional context", () => {
-            expect(CSSselect.selectAll(".a", document)).toHaveLength(3); // No context found 3 elements (.a)
-            expect(
-                CSSselect.selectAll(
-                    ".a",
-                    CSSselect.selectAll("#boosh", document)
-                )
-            ).toHaveLength(2); // Context found 2 elements (#boosh .a)
+            expect(selectAll(".a")).toHaveLength(3); // No context found 3 elements (.a)
+            expect(selectAll(".a", selectAll("#boosh"))).toHaveLength(2); // Context found 2 elements (#boosh .a)
         });
 
-        it.skip("should be able to pass qwery result as context", () => {
-            expect(
-                CSSselect.selectAll(
-                    ".a",
-                    CSSselect.selectAll("#boosh", document)
-                )
-            ).toHaveLength(2); // Context found 2 elements(.a, #boosh)
-            expect(
-                CSSselect.selectAll(".a", CSSselect.selectAll(".a", document))
-            ).toHaveLength(0); // Context found 0 elements(.a, .a)
-            expect(
-                CSSselect.selectAll(".a", CSSselect.selectAll(".b", document))
-            ).toHaveLength(1); // Context found 1 elements(.a, .b)
-            expect(
-                CSSselect.selectAll(
-                    ".a",
-                    CSSselect.selectAll("#boosh .b", document)
-                )
-            ).toHaveLength(1); // Context found 1 elements(.a, #boosh .b)
-            expect(
-                CSSselect.selectAll(
-                    ".b",
-                    CSSselect.selectAll("#boosh .b", document)
-                )
-            ).toHaveLength(0); // Context found 0 elements(.b, #boosh .b)
+        it("should be able to pass qwery result as context", () => {
+            expect(selectAll(".a", selectAll("#boosh"))).toHaveLength(2); // Context found 2 elements(.a, #boosh)
+            expect(selectAll("> .a", selectAll(".a"))).toHaveLength(1); // Context found 0 elements(.a, .a)
+            expect(selectAll("> .a", selectAll(".b"))).toHaveLength(1); // Context found 1 elements(.a, .b)
+            expect(selectAll("> .a", selectAll("#boosh .b"))).toHaveLength(1); // Context found 1 elements(.a, #boosh .b)
+            expect(selectAll("> .b", selectAll("#boosh .b"))).toHaveLength(0); // Context found 0 elements(.b, #boosh .b)
         });
 
         it("should not return duplicates from combinators", () => {
-            expect(CSSselect.selectAll("#boosh,#boosh", document)).toHaveLength(
-                1
-            ); // Two booshes dont make a thing go right
-            expect(
-                CSSselect.selectAll("#boosh,.apples,#boosh", document)
-            ).toHaveLength(1); // Two booshes and an apple dont make a thing go right
+            expect(selectAll("#boosh,#boosh")).toHaveLength(1); // Two booshes dont make a thing go right
+            expect(selectAll("#boosh,.apples,#boosh")).toHaveLength(1); // Two booshes and an apple dont make a thing go right
         });
 
         it("byId sub-queries within context", () => {
+            expect(selectAll("#booshTest", selectAll("#boosh"))).toHaveLength(
+                1
+            ); // Found "#id #id"
             expect(
-                CSSselect.selectAll(
-                    "#booshTest",
-                    CSSselect.selectAll("#boosh", document)
-                )
-            ).toHaveLength(1); // Found "#id #id"
-            expect(
-                CSSselect.selectAll(
-                    ".a.b #booshTest",
-                    CSSselect.selectAll("#boosh", document)
-                )
+                selectAll(".a.b #booshTest", selectAll("#boosh"))
             ).toHaveLength(1); // Found ".class.class #id"
             expect(
-                CSSselect.selectAll(
-                    ".a>#booshTest",
-                    CSSselect.selectAll("#boosh", document)
-                )
+                selectAll(".a>#booshTest", selectAll("#boosh"))
             ).toHaveLength(1); // Found ".class>#id"
             expect(
-                CSSselect.selectAll(
-                    ">.a>#booshTest",
-                    CSSselect.selectAll("#boosh", document)
-                )
+                selectAll(">.a>#booshTest", selectAll("#boosh"))
             ).toHaveLength(1); // Found ">.class>#id"
-            expect(
-                CSSselect.selectAll(
-                    "#boosh",
-                    CSSselect.selectAll("#booshTest", document)
-                )
-            ).toHaveLength(0); // Shouldn't find #boosh (ancestor) within #booshTest (descendent)
-            expect(
-                CSSselect.selectAll(
-                    "#boosh",
-                    CSSselect.selectAll("#lonelyBoosh", document)
-                )
-            ).toHaveLength(0); // Shouldn't find #boosh within #lonelyBoosh (unrelated)
+            expect(selectAll("#boosh", selectAll("#booshTest"))).toHaveLength(
+                0
+            ); // Shouldn't find #boosh (ancestor) within #booshTest (descendent)
+            expect(selectAll("#boosh", selectAll("#lonelyBoosh"))).toHaveLength(
+                0
+            ); // Shouldn't find #boosh within #lonelyBoosh (unrelated)
         });
     });
 
     describe("CSS 1", () => {
         it("get element by id", () => {
-            const result = CSSselect.selectAll("#boosh", document);
+            const result = selectAll("#boosh");
             expect(result[0]).toBeTruthy(); // Found element with id=boosh
-            expect(CSSselect.selectAll("h1", document)[0]).toBeTruthy(); // Found 1 h1
+            expect(selectAll("h1")[0]).toBeTruthy(); // Found 1 h1
         });
 
         it("byId sub-queries", () => {
-            expect(
-                CSSselect.selectAll("#boosh #booshTest", document)
-            ).toHaveLength(1); // Found "#id #id"
-            expect(
-                CSSselect.selectAll(".a.b #booshTest", document)
-            ).toHaveLength(1); // Found ".class.class #id"
-            expect(
-                CSSselect.selectAll("#boosh>.a>#booshTest", document)
-            ).toHaveLength(1); // Found "#id>.class>#id"
-            expect(CSSselect.selectAll(".a>#booshTest", document)).toHaveLength(
-                1
-            ); // Found ".class>#id"
+            expect(selectAll("#boosh #booshTest")).toHaveLength(1); // Found "#id #id"
+            expect(selectAll(".a.b #booshTest")).toHaveLength(1); // Found ".class.class #id"
+            expect(selectAll("#boosh>.a>#booshTest")).toHaveLength(1); // Found "#id>.class>#id"
+            expect(selectAll(".a>#booshTest")).toHaveLength(1); // Found ".class>#id"
         });
 
         it("get elements by class", () => {
-            expect(CSSselect.selectAll("#boosh .a", document)).toHaveLength(2); // Found two elements
-            expect(
-                CSSselect.selectAll("#boosh div.a", document)[0]
-            ).toBeTruthy(); // Found one element
-            expect(CSSselect.selectAll("#boosh div", document)).toHaveLength(2); // Found two {div} elements
-            expect(
-                CSSselect.selectAll("#boosh span", document)[0]
-            ).toBeTruthy(); // Found one {span} element
-            expect(
-                CSSselect.selectAll("#boosh div div", document)[0]
-            ).toBeTruthy(); // Found a single div
-            expect(CSSselect.selectAll("a.odd", document)).toHaveLength(1); // Found single a
+            expect(selectAll("#boosh .a")).toHaveLength(2); // Found two elements
+            expect(selectAll("#boosh div.a")[0]).toBeTruthy(); // Found one element
+            expect(selectAll("#boosh div")).toHaveLength(2); // Found two {div} elements
+            expect(selectAll("#boosh span")[0]).toBeTruthy(); // Found one {span} element
+            expect(selectAll("#boosh div div")[0]).toBeTruthy(); // Found a single div
+            expect(selectAll("a.odd")).toHaveLength(1); // Found single a
         });
 
         it("combos", () => {
-            expect(
-                CSSselect.selectAll("#boosh div,#boosh span", document)
-            ).toHaveLength(3); // Found 2 divs and 1 span
+            expect(selectAll("#boosh div,#boosh span")).toHaveLength(3); // Found 2 divs and 1 span
         });
 
         it("class with dashes", () => {
-            expect(
-                CSSselect.selectAll(".class-with-dashes", document)
-            ).toHaveLength(1); // Found something
+            expect(selectAll(".class-with-dashes")).toHaveLength(1); // Found something
         });
 
         it("should ignore comment nodes", () => {
-            expect(CSSselect.selectAll("#boosh *", document)).toHaveLength(4); // Found only 4 elements under #boosh
+            expect(selectAll("#boosh *")).toHaveLength(4); // Found only 4 elements under #boosh
         });
 
         it("deep messy relationships", () => {
@@ -197,34 +136,20 @@ describe("qwery", () => {
              * they are useful for making sure the dom crawler doesn't stop short or over-extend as it works
              * up the tree the crawl needs to be comprehensive
              */
+            expect(selectAll("div#fixtures > div a")).toHaveLength(5); // Found four results for "div#fixtures > div a"
             expect(
-                CSSselect.selectAll("div#fixtures > div a", document)
-            ).toHaveLength(5); // Found four results for "div#fixtures > div a"
-            expect(
-                CSSselect.selectAll(
-                    ".direct-descend > .direct-descend .lvl2",
-                    document
-                )
+                selectAll(".direct-descend > .direct-descend .lvl2")
             ).toHaveLength(1); // Found one result for ".direct-descend > .direct-descend .lvl2"
             expect(
-                CSSselect.selectAll(
-                    ".direct-descend > .direct-descend div",
-                    document
-                )
+                selectAll(".direct-descend > .direct-descend div")
             ).toHaveLength(1); // Found one result for ".direct-descend > .direct-descend div"
             expect(
-                CSSselect.selectAll(
-                    ".direct-descend > .direct-descend div",
-                    document
-                )
+                selectAll(".direct-descend > .direct-descend div")
             ).toHaveLength(1); // Found one result for ".direct-descend > .direct-descend div"
+            expect(selectAll("div#fixtures div ~ a div")).toHaveLength(0); // Found no results for odd query
             expect(
-                CSSselect.selectAll("div#fixtures div ~ a div", document)
-            ).toHaveLength(0); // Found no results for odd query
-            expect(
-                CSSselect.selectAll(
-                    ".direct-descend > .direct-descend > .direct-descend ~ .lvl2",
-                    document
+                selectAll(
+                    ".direct-descend > .direct-descend > .direct-descend ~ .lvl2"
                 )
             ).toHaveLength(0); // Found no results for another odd query
         });
@@ -232,33 +157,22 @@ describe("qwery", () => {
 
     describe("CSS 2", () => {
         it("get elements by attribute", () => {
-            const wanted = CSSselect.selectAll("#boosh div[test]", document)[0];
-            const expected = DomUtils.getElementById("booshTest", document);
+            const wanted = selectAll("#boosh div[test]")[0];
+            const expected = document.getElementById("booshTest");
             expect(wanted).toBe(expected); // Found attribute
-            expect(
-                CSSselect.selectAll("#boosh div[test=fg]", document)[0]
-            ).toBe(expected); // Found attribute with value
-            expect(
-                CSSselect.selectAll('em[rel~="copyright"]', document)
-            ).toHaveLength(1); // Found em[rel~="copyright"]
-            expect(
-                CSSselect.selectAll('em[nopass~="copyright"]', document)
-            ).toHaveLength(0); // Found em[nopass~="copyright"]
+            expect(selectAll("#boosh div[test=fg]")[0]).toBe(expected); // Found attribute with value
+            expect(selectAll('em[rel~="copyright"]')).toHaveLength(1); // Found em[rel~="copyright"]
+            expect(selectAll('em[nopass~="copyright"]')).toHaveLength(0); // Found em[nopass~="copyright"]
         });
 
         it("should not throw error by attribute selector", () => {
-            expect(CSSselect.selectAll('[foo^="bar"]', document)).toHaveLength(
-                1
-            ); // Found 1 element
+            expect(selectAll('[foo^="bar"]')).toHaveLength(1); // Found 1 element
         });
 
         it("crazy town", () => {
-            const el = DomUtils.getElementById("attr-test3", document);
+            const el = document.getElementById("attr-test3");
             expect(
-                CSSselect.selectAll(
-                    'div#attr-test3.found.you[title="whatup duders"]',
-                    document
-                )[0]
+                selectAll('div#attr-test3.found.you[title="whatup duders"]')[0]
             ).toBe(el); // Found the right element
         });
     });
@@ -267,269 +181,169 @@ describe("qwery", () => {
         /* CSS 2 SPEC */
 
         it("[attr]", () => {
-            const expected = DomUtils.getElementById("attr-test-1", document);
-            expect(
-                CSSselect.selectAll("#attributes div[unique-test]", document)[0]
-            ).toBe(expected); // Found attribute with [attr]
+            const expected = document.getElementById("attr-test-1");
+            expect(selectAll("#attributes div[unique-test]")[0]).toBe(expected); // Found attribute with [attr]
         });
 
         it("[attr=val]", () => {
-            const expected = DomUtils.getElementById("attr-test-2", document);
-            expect(
-                CSSselect.selectAll(
-                    '#attributes div[test="two-foo"]',
-                    document
-                )[0]
-            ).toBe(expected); // Found attribute with =
-            expect(
-                CSSselect.selectAll(
-                    "#attributes div[test='two-foo']",
-                    document
-                )[0]
-            ).toBe(expected); // Found attribute with =
-            expect(
-                CSSselect.selectAll(
-                    "#attributes div[test=two-foo]",
-                    document
-                )[0]
-            ).toBe(expected); // Found attribute with =
+            const expected = document.getElementById("attr-test-2");
+            expect(selectAll('#attributes div[test="two-foo"]')[0]).toBe(
+                expected
+            ); // Found attribute with =
+            expect(selectAll("#attributes div[test='two-foo']")[0]).toBe(
+                expected
+            ); // Found attribute with =
+            expect(selectAll("#attributes div[test=two-foo]")[0]).toBe(
+                expected
+            ); // Found attribute with =
         });
 
         it("[attr~=val]", () => {
-            const expected = DomUtils.getElementById("attr-test-3", document);
-            expect(
-                CSSselect.selectAll("#attributes div[test~=three]", document)[0]
-            ).toBe(expected); // Found attribute with ~=
+            const expected = document.getElementById("attr-test-3");
+            expect(selectAll("#attributes div[test~=three]")[0]).toBe(expected); // Found attribute with ~=
         });
 
         it("[attr|=val]", () => {
-            const expected = DomUtils.getElementById("attr-test-2", document);
-            expect(
-                CSSselect.selectAll(
-                    '#attributes div[test|="two-foo"]',
-                    document
-                )[0]
-            ).toBe(expected); // Found attribute with |=
-            expect(
-                CSSselect.selectAll("#attributes div[test|=two]", document)[0]
-            ).toBe(expected); // Found attribute with |=
+            const expected = document.getElementById("attr-test-2");
+            expect(selectAll('#attributes div[test|="two-foo"]')[0]).toBe(
+                expected
+            ); // Found attribute with |=
+            expect(selectAll("#attributes div[test|=two]")[0]).toBe(expected); // Found attribute with |=
         });
 
         it("[href=#x] special case", () => {
-            const expected = DomUtils.getElementById("attr-test-4", document);
-            expect(
-                CSSselect.selectAll('#attributes a[href="#aname"]', document)[0]
-            ).toBe(expected); // Found attribute with href=#x
+            const expected = document.getElementById("attr-test-4");
+            expect(selectAll('#attributes a[href="#aname"]')[0]).toBe(expected); // Found attribute with href=#x
         });
 
         /* CSS 3 SPEC */
 
         it("[attr^=val]", () => {
-            const expected = DomUtils.getElementById("attr-test-2", document);
-            expect(
-                CSSselect.selectAll("#attributes div[test^=two]", document)[0]
-            ).toBe(expected); // Found attribute with ^=
+            const expected = document.getElementById("attr-test-2");
+            expect(selectAll("#attributes div[test^=two]")[0]).toBe(expected); // Found attribute with ^=
         });
 
         it("[attr$=val]", () => {
-            const expected = DomUtils.getElementById("attr-test-2", document);
-            expect(
-                CSSselect.selectAll("#attributes div[test$=foo]", document)[0]
-            ).toBe(expected); // Found attribute with $=
+            const expected = document.getElementById("attr-test-2");
+            expect(selectAll("#attributes div[test$=foo]")[0]).toBe(expected); // Found attribute with $=
         });
 
         it("[attr*=val]", () => {
-            const expected = DomUtils.getElementById("attr-test-3", document);
-            expect(
-                CSSselect.selectAll("#attributes div[test*=hree]", document)[0]
-            ).toBe(expected); // Found attribute with *=
+            const expected = document.getElementById("attr-test-3");
+            expect(selectAll("#attributes div[test*=hree]")[0]).toBe(expected); // Found attribute with *=
         });
 
         it("direct descendants", () => {
+            expect(selectAll("#direct-descend > .direct-descend")).toHaveLength(
+                2
+            ); // Found two direct descendents
             expect(
-                CSSselect.selectAll(
-                    "#direct-descend > .direct-descend",
-                    document
-                )
-            ).toHaveLength(2); // Found two direct descendents
-            expect(
-                CSSselect.selectAll(
-                    "#direct-descend > .direct-descend > .lvl2",
-                    document
-                )
+                selectAll("#direct-descend > .direct-descend > .lvl2")
             ).toHaveLength(3); // Found three second-level direct descendents
         });
 
         it("sibling elements", () => {
             expect(
-                CSSselect.selectAll(
-                    "#sibling-selector ~ .sibling-selector",
-                    document
-                )
+                selectAll("#sibling-selector ~ .sibling-selector")
             ).toHaveLength(2); // Found two siblings
             expect(
-                CSSselect.selectAll(
-                    "#sibling-selector ~ div.sibling-selector",
-                    document
-                )
+                selectAll("#sibling-selector ~ div.sibling-selector")
             ).toHaveLength(2); // Found two siblings
             expect(
-                CSSselect.selectAll(
-                    "#sibling-selector + div.sibling-selector",
-                    document
-                )
+                selectAll("#sibling-selector + div.sibling-selector")
             ).toHaveLength(1); // Found one sibling
             expect(
-                CSSselect.selectAll(
-                    "#sibling-selector + .sibling-selector",
-                    document
-                )
+                selectAll("#sibling-selector + .sibling-selector")
             ).toHaveLength(1); // Found one sibling
 
-            expect(
-                CSSselect.selectAll(".parent .oldest ~ .sibling", document)
-            ).toHaveLength(4); // Found four younger siblings
-            expect(
-                CSSselect.selectAll(".parent .middle ~ .sibling", document)
-            ).toHaveLength(2); // Found two younger siblings
-            expect(
-                CSSselect.selectAll(".parent .middle ~ h4", document)
-            ).toHaveLength(1); // Found next sibling by tag
-            expect(
-                CSSselect.selectAll(".parent .middle ~ h4.younger", document)
-            ).toHaveLength(1); // Found next sibling by tag and class
-            expect(
-                CSSselect.selectAll(".parent .middle ~ h3", document)
-            ).toHaveLength(0); // An element can't be its own sibling
-            expect(
-                CSSselect.selectAll(".parent .middle ~ h2", document)
-            ).toHaveLength(0); // Didn't find an older sibling
-            expect(
-                CSSselect.selectAll(".parent .youngest ~ .sibling", document)
-            ).toHaveLength(0); // Found no younger siblings
-
-            expect(
-                CSSselect.selectAll(".parent .oldest + .sibling", document)
-            ).toHaveLength(1); // Found next sibling
-            expect(
-                CSSselect.selectAll(".parent .middle + .sibling", document)
-            ).toHaveLength(1); // Found next sibling
-            expect(
-                CSSselect.selectAll(".parent .middle + h4", document)
-            ).toHaveLength(1); // Found next sibling by tag
-            expect(
-                CSSselect.selectAll(".parent .middle + h3", document)
-            ).toHaveLength(0); // An element can't be its own sibling
-            expect(
-                CSSselect.selectAll(".parent .middle + h2", document)
-            ).toHaveLength(0); // Didn't find an older sibling
-            expect(
-                CSSselect.selectAll(".parent .youngest + .sibling", document)
-            ).toHaveLength(0); // Found no younger siblings
+            expect(selectAll(".parent .oldest ~ .sibling")).toHaveLength(4); // Found four younger siblings
+            expect(selectAll(".parent .middle ~ .sibling")).toHaveLength(2); // Found two younger siblings
+            expect(selectAll(".parent .middle ~ h4")).toHaveLength(1); // Found next sibling by tag
+            expect(selectAll(".parent .middle ~ h4.younger")).toHaveLength(1); // Found next sibling by tag and class
+            expect(selectAll(".parent .middle ~ h3")).toHaveLength(0); // An element can't be its own sibling
+            expect(selectAll(".parent .middle ~ h2")).toHaveLength(0); // Didn't find an older sibling
+            expect(selectAll(".parent .youngest ~ .sibling")).toHaveLength(0); // Found no younger siblings
+
+            expect(selectAll(".parent .oldest + .sibling")).toHaveLength(1); // Found next sibling
+            expect(selectAll(".parent .middle + .sibling")).toHaveLength(1); // Found next sibling
+            expect(selectAll(".parent .middle + h4")).toHaveLength(1); // Found next sibling by tag
+            expect(selectAll(".parent .middle + h3")).toHaveLength(0); // An element can't be its own sibling
+            expect(selectAll(".parent .middle + h2")).toHaveLength(0); // Didn't find an older sibling
+            expect(selectAll(".parent .youngest + .sibling")).toHaveLength(0); // Found no younger siblings
         });
     });
 
     describe("element-context queries", () => {
         it("relationship-first queries", () => {
             expect(
-                CSSselect.selectAll(
-                    "> .direct-descend",
-                    CSSselect.selectAll("#direct-descend", document)
-                )
+                selectAll("> .direct-descend", selectAll("#direct-descend"))
             ).toHaveLength(2); // Found two direct descendents using > first
             expect(
-                CSSselect.selectAll(
-                    "~ .sibling-selector",
-                    CSSselect.selectAll("#sibling-selector", document)
-                )
+                selectAll("~ .sibling-selector", selectAll("#sibling-selector"))
             ).toHaveLength(2); // Found two siblings with ~ first
             expect(
-                CSSselect.selectAll(
-                    "+ .sibling-selector",
-                    CSSselect.selectAll("#sibling-selector", document)
-                )
+                selectAll("+ .sibling-selector", selectAll("#sibling-selector"))
             ).toHaveLength(1); // Found one sibling with + first
             expect(
-                CSSselect.selectAll(
-                    "> .tokens a",
-                    CSSselect.selectAll(".idless", document)[0]
-                )
+                selectAll("> .tokens a", selectAll(".idless")[0])
             ).toHaveLength(1); // Found one sibling from a root with no id
         });
 
         // Should be able to query on an element that hasn't been inserted into the dom
         it("detached fragments", () => {
-            expect(CSSselect.selectAll(".a span", frag)).toHaveLength(1); // Should find child elements of fragment
-            expect(CSSselect.selectAll("> div p em", frag)).toHaveLength(2); // Should find child elements of fragment, relationship first
+            expect(selectAll(".a span", frag)).toHaveLength(1); // Should find child elements of fragment
+            expect(selectAll("> div p em", frag)).toHaveLength(2); // Should find child elements of fragment, relationship first
         });
 
         it("byId sub-queries within detached fragment", () => {
-            expect(CSSselect.selectAll("#emem", frag)).toHaveLength(1); // Found "#id" in fragment
-            expect(CSSselect.selectAll(".d.i #emem", frag)).toHaveLength(1); // Found ".class.class #id" in fragment
-            expect(CSSselect.selectAll(".d #oooo #emem", frag)).toHaveLength(1); // Found ".class #id #id" in fragment
-            expect(CSSselect.selectAll("> div #oooo", frag)).toHaveLength(1); // Found "> .class #id" in fragment
-            expect(
-                CSSselect.selectAll("#oooo", CSSselect.selectAll("#emem", frag))
-            ).toHaveLength(0); // Shouldn't find #oooo (ancestor) within #emem (descendent)
-            expect(
-                CSSselect.selectAll("#sep", CSSselect.selectAll("#emem", frag))
-            ).toHaveLength(0); // Shouldn't find #sep within #emem (unrelated)
+            expect(selectAll("#emem", frag)).toHaveLength(1); // Found "#id" in fragment
+            expect(selectAll(".d.i #emem", frag)).toHaveLength(1); // Found ".class.class #id" in fragment
+            expect(selectAll(".d #oooo #emem", frag)).toHaveLength(1); // Found ".class #id #id" in fragment
+            expect(selectAll("> div #oooo", frag)).toHaveLength(1); // Found "> .class #id" in fragment
+            expect(selectAll("#oooo", selectAll("#emem", frag))).toHaveLength(
+                0
+            ); // Shouldn't find #oooo (ancestor) within #emem (descendent)
+            expect(selectAll("#sep", selectAll("#emem", frag))).toHaveLength(0); // Shouldn't find #sep within #emem (unrelated)
         });
 
         it("exclude self in match", () => {
             expect(
-                CSSselect.selectAll(
-                    ".order-matters",
-                    CSSselect.selectAll("#order-matters", document)[0]
-                )
+                selectAll(".order-matters", selectAll("#order-matters")[0])
             ).toHaveLength(4); // Should not include self in element-context queries
         });
 
         // Because form's have .length
         it("forms can be used as contexts", () => {
-            expect(
-                CSSselect.selectAll(
-                    "*",
-                    CSSselect.selectAll("form", document)[0]
-                )
-            ).toHaveLength(3); // Found 3 elements under &lt;form&gt;
+            expect(selectAll("*", selectAll("form")[0])).toHaveLength(3); // Found 3 elements under &lt;form&gt;
         });
     });
 
     describe("tokenizer", () => {
         it("should not get weird tokens", () => {
-            expect(
-                CSSselect.selectAll('div .tokens[title="one"]', document)[0]
-            ).toBe(DomUtils.getElementById("token-one", document)); // Found div .tokens[title="one"]
-            expect(
-                CSSselect.selectAll('div .tokens[title="one two"]', document)[0]
-            ).toBe(DomUtils.getElementById("token-two", document)); // Found div .tokens[title="one two"]
-            expect(
-                CSSselect.selectAll(
-                    'div .tokens[title="one two three #%"]',
-                    document
+            expect(selectAll('div .tokens[title="one"]')[0]).toBe(
+                document.getElementById("token-one")
+            ); // Found div .tokens[title="one"]
+            expect(selectAll('div .tokens[title="one two"]')[0]).toBe(
+                document.getElementById("token-two")
+            ); // Found div .tokens[title="one two"]
+            expect(selectAll('div .tokens[title="one two three #%"]')[0]).toBe(
+                document.getElementById("token-three")
+            ); // Found div .tokens[title="one two three #%"]
+            expect(
+                selectAll("div .tokens[title='one two three #%'] a")[0]
+            ).toBe(document.getElementById("token-four")); // Found div .tokens[title=\'one two three #%\'] a
+            expect(
+                selectAll(
+                    'div .tokens[title="one two three #%"] a[href$=foo] div'
                 )[0]
-            ).toBe(DomUtils.getElementById("token-three", document)); // Found div .tokens[title="one two three #%"]
-            expect(
-                CSSselect.selectAll(
-                    "div .tokens[title='one two three #%'] a",
-                    document
-                )[0]
-            ).toBe(DomUtils.getElementById("token-four", document)); // Found div .tokens[title=\'one two three #%\'] a
-            expect(
-                CSSselect.selectAll(
-                    'div .tokens[title="one two three #%"] a[href$=foo] div',
-                    document
-                )[0]
-            ).toBe(DomUtils.getElementById("token-five", document)); // Found div .tokens[title="one two three #%"] a[href=foo] div
+            ).toBe(document.getElementById("token-five")); // Found div .tokens[title="one two three #%"] a[href=foo] div
         });
     });
 
     describe("interesting syntaxes", () => {
         it("should parse bad selectors", () => {
             expect(
-                CSSselect.selectAll("#spaced-tokens    p    em    a", document)
-                    .length
+                selectAll("#spaced-tokens    p    em    a").length
             ).toBeTruthy(); // Found element with funny tokens
         });
     });
@@ -548,10 +362,7 @@ describe("qwery", () => {
             function tag(el: Element) {
                 return el.name.toLowerCase();
             }
-            const els = CSSselect.selectAll(
-                "#order-matters .order-matters",
-                document
-            ) as Element[];
+            const els = selectAll("#order-matters .order-matters") as Element[];
             expect(tag(els[0])).toBe("p"); // First element matched is a {p} tag
             expect(tag(els[1])).toBe("a"); // First element matched is a {a} tag
             expect(tag(els[2])).toBe("em"); // First element matched is a {em} tag
@@ -561,242 +372,140 @@ describe("qwery", () => {
 
     describe("pseudo-selectors", () => {
         it(":contains", () => {
-            expect(
-                CSSselect.selectAll("li:contains(humans)", document)
-            ).toHaveLength(1); // Found by "element:contains(text)"
-            expect(
-                CSSselect.selectAll(":contains(humans)", document)
-            ).toHaveLength(5); // Found by ":contains(text)", including all ancestors
+            expect(selectAll("li:contains(humans)")).toHaveLength(1); // Found by "element:contains(text)"
+            expect(selectAll(":contains(humans)")).toHaveLength(5); // Found by ":contains(text)", including all ancestors
             // * Is an important case, can cause weird errors
-            expect(
-                CSSselect.selectAll("*:contains(humans)", document)
-            ).toHaveLength(5); // Found by "*:contains(text)", including all ancestors
-            expect(
-                CSSselect.selectAll("ol:contains(humans)", document)
-            ).toHaveLength(1); // Found by "ancestor:contains(text)"
+            expect(selectAll("*:contains(humans)")).toHaveLength(5); // Found by "*:contains(text)", including all ancestors
+            expect(selectAll("ol:contains(humans)")).toHaveLength(1); // Found by "ancestor:contains(text)"
         });
 
         it(":not", () => {
-            expect(CSSselect.selectAll(".odd:not(div)", document)).toHaveLength(
-                1
-            ); // Found one .odd :not an &lt;a&gt;
+            expect(selectAll(".odd:not(div)")).toHaveLength(1); // Found one .odd :not an &lt;a&gt;
         });
 
         it(":first-child", () => {
-            expect(
-                CSSselect.selectAll("#pseudos div:first-child", document)[0]
-            ).toBe(pseudos[0]); // Found first child
-            expect(
-                CSSselect.selectAll("#pseudos div:first-child", document)
-            ).toHaveLength(1); // Found only 1
+            expect(selectAll("#pseudos div:first-child")[0]).toBe(pseudos[0]); // Found first child
+            expect(selectAll("#pseudos div:first-child")).toHaveLength(1); // Found only 1
         });
 
         it(":last-child", () => {
             const all = DomUtils.getElementsByTagName("div", pseudos);
-            expect(
-                CSSselect.selectAll("#pseudos div:last-child", document)[0]
-            ).toBe(all[all.length - 1]); // Found last child
-            expect(
-                CSSselect.selectAll("#pseudos div:last-child", document)
-            ).toHaveLength(1); // Found only 1
+            expect(selectAll("#pseudos div:last-child")[0]).toBe(
+                all[all.length - 1]
+            ); // Found last child
+            expect(selectAll("#pseudos div:last-child")).toHaveLength(1); // Found only 1
         });
 
         it('ol > li[attr="boosh"]:last-child', () => {
-            const expected = DomUtils.getElementById(
-                "attr-child-boosh",
-                document
-            );
-            expect(
-                CSSselect.selectAll(
-                    'ol > li[attr="boosh"]:last-child',
-                    document
-                )
-            ).toHaveLength(1); // Only 1 element found
-            expect(
-                CSSselect.selectAll(
-                    'ol > li[attr="boosh"]:last-child',
-                    document
-                )[0]
-            ).toBe(expected); // Found correct element
+            const expected = document.getElementById("attr-child-boosh");
+            expect(selectAll('ol > li[attr="boosh"]:last-child')).toHaveLength(
+                1
+            ); // Only 1 element found
+            expect(selectAll('ol > li[attr="boosh"]:last-child')[0]).toBe(
+                expected
+            ); // Found correct element
         });
 
         it(":nth-child(odd|even|x)", () => {
             const second = DomUtils.getElementsByTagName("div", pseudos)[1];
-            expect(
-                CSSselect.selectAll("#pseudos :nth-child(odd)", document)
-            ).toHaveLength(4); // Found 4 odd elements
-            expect(
-                CSSselect.selectAll("#pseudos div:nth-child(odd)", document)
-            ).toHaveLength(3); // Found 3 odd elements with div tag
-            expect(
-                CSSselect.selectAll("#pseudos div:nth-child(even)", document)
-            ).toHaveLength(3); // Found 3 even elements with div tag
-            expect(
-                CSSselect.selectAll("#pseudos div:nth-child(2)", document)[0]
-            ).toBe(second); // Found 2nd nth-child of pseudos
+            expect(selectAll("#pseudos :nth-child(odd)")).toHaveLength(4); // Found 4 odd elements
+            expect(selectAll("#pseudos div:nth-child(odd)")).toHaveLength(3); // Found 3 odd elements with div tag
+            expect(selectAll("#pseudos div:nth-child(even)")).toHaveLength(3); // Found 3 even elements with div tag
+            expect(selectAll("#pseudos div:nth-child(2)")[0]).toBe(second); // Found 2nd nth-child of pseudos
         });
 
         it(":nth-child(expr)", () => {
             const fifth = DomUtils.getElementsByTagName("a", pseudos)[0];
             const sixth = DomUtils.getElementsByTagName("div", pseudos)[4];
 
-            expect(
-                CSSselect.selectAll("#pseudos :nth-child(3n+1)", document)
-            ).toHaveLength(3); // Found 3 elements
-            expect(
-                CSSselect.selectAll("#pseudos :nth-child(+3n-2)", document)
-            ).toHaveLength(3); // Found 3 elements'
-            expect(
-                CSSselect.selectAll("#pseudos :nth-child(-n+6)", document)
-            ).toHaveLength(6); // Found 6 elements
-            expect(
-                CSSselect.selectAll("#pseudos :nth-child(-n+5)", document)
-            ).toHaveLength(5); // Found 5 elements
-            expect(
-                CSSselect.selectAll("#pseudos :nth-child(3n+2)", document)[1]
-            ).toBe(fifth); // Second :nth-child(3n+2) is the fifth child
-            expect(
-                CSSselect.selectAll("#pseudos :nth-child(3n)", document)[1]
-            ).toBe(sixth); // Second :nth-child(3n) is the sixth child
+            expect(selectAll("#pseudos :nth-child(3n+1)")).toHaveLength(3); // Found 3 elements
+            expect(selectAll("#pseudos :nth-child(+3n-2)")).toHaveLength(3); // Found 3 elements'
+            expect(selectAll("#pseudos :nth-child(-n+6)")).toHaveLength(6); // Found 6 elements
+            expect(selectAll("#pseudos :nth-child(-n+5)")).toHaveLength(5); // Found 5 elements
+            expect(selectAll("#pseudos :nth-child(3n+2)")[1]).toBe(fifth); // Second :nth-child(3n+2) is the fifth child
+            expect(selectAll("#pseudos :nth-child(3n)")[1]).toBe(sixth); // Second :nth-child(3n) is the sixth child
         });
 
         it(":nth-last-child(odd|even|x)", () => {
             const second = DomUtils.getElementsByTagName("div", pseudos)[1];
-            expect(
-                CSSselect.selectAll("#pseudos :nth-last-child(odd)", document)
-            ).toHaveLength(4); // Found 4 odd elements
-            expect(
-                CSSselect.selectAll(
-                    "#pseudos div:nth-last-child(odd)",
-                    document
-                )
-            ).toHaveLength(3); // Found 3 odd elements with div tag
-            expect(
-                CSSselect.selectAll(
-                    "#pseudos div:nth-last-child(even)",
-                    document
-                )
-            ).toHaveLength(3); // Found 3 even elements with div tag
-            expect(
-                CSSselect.selectAll(
-                    "#pseudos div:nth-last-child(6)",
-                    document
-                )[0]
-            ).toBe(second); // 6th nth-last-child should be 2nd of 7 elements
+            expect(selectAll("#pseudos :nth-last-child(odd)")).toHaveLength(4); // Found 4 odd elements
+            expect(selectAll("#pseudos div:nth-last-child(odd)")).toHaveLength(
+                3
+            ); // Found 3 odd elements with div tag
+            expect(selectAll("#pseudos div:nth-last-child(even)")).toHaveLength(
+                3
+            ); // Found 3 even elements with div tag
+            expect(selectAll("#pseudos div:nth-last-child(6)")[0]).toBe(second); // 6th nth-last-child should be 2nd of 7 elements
         });
 
         it(":nth-last-child(expr)", () => {
             const third = DomUtils.getElementsByTagName("div", pseudos)[2];
 
-            expect(
-                CSSselect.selectAll("#pseudos :nth-last-child(3n+1)", document)
-            ).toHaveLength(3); // Found 3 elements
-            expect(
-                CSSselect.selectAll("#pseudos :nth-last-child(3n-2)", document)
-            ).toHaveLength(3); // Found 3 elements
-            expect(
-                CSSselect.selectAll("#pseudos :nth-last-child(-n+6)", document)
-            ).toHaveLength(6); // Found 6 elements
-            expect(
-                CSSselect.selectAll("#pseudos :nth-last-child(-n+5)", document)
-            ).toHaveLength(5); // Found 5 elements
-            expect(
-                CSSselect.selectAll(
-                    "#pseudos :nth-last-child(3n+2)",
-                    document
-                )[0]
-            ).toBe(third); // First :nth-last-child(3n+2) is the third child
+            expect(selectAll("#pseudos :nth-last-child(3n+1)")).toHaveLength(3); // Found 3 elements
+            expect(selectAll("#pseudos :nth-last-child(3n-2)")).toHaveLength(3); // Found 3 elements
+            expect(selectAll("#pseudos :nth-last-child(-n+6)")).toHaveLength(6); // Found 6 elements
+            expect(selectAll("#pseudos :nth-last-child(-n+5)")).toHaveLength(5); // Found 5 elements
+            expect(selectAll("#pseudos :nth-last-child(3n+2)")[0]).toBe(third); // First :nth-last-child(3n+2) is the third child
         });
 
         it(":nth-of-type(expr)", () => {
             const a = DomUtils.getElementsByTagName("a", pseudos)[0];
 
-            expect(
-                CSSselect.selectAll("#pseudos div:nth-of-type(3n+1)", document)
-            ).toHaveLength(2); // Found 2 div elements
-            expect(
-                CSSselect.selectAll("#pseudos a:nth-of-type(3n+1)", document)
-            ).toHaveLength(1); // Found 1 a element
-            expect(
-                CSSselect.selectAll("#pseudos a:nth-of-type(3n+1)", document)[0]
-            ).toBe(a); // Found the right a element
-            expect(
-                CSSselect.selectAll("#pseudos a:nth-of-type(3n)", document)
-            ).toHaveLength(0); // No matches for every third a
-            expect(
-                CSSselect.selectAll("#pseudos a:nth-of-type(odd)", document)
-            ).toHaveLength(1); // Found the odd a
-            expect(
-                CSSselect.selectAll("#pseudos a:nth-of-type(1)", document)
-            ).toHaveLength(1); // Found the first a
+            expect(selectAll("#pseudos div:nth-of-type(3n+1)")).toHaveLength(2); // Found 2 div elements
+            expect(selectAll("#pseudos a:nth-of-type(3n+1)")).toHaveLength(1); // Found 1 a element
+            expect(selectAll("#pseudos a:nth-of-type(3n+1)")[0]).toBe(a); // Found the right a element
+            expect(selectAll("#pseudos a:nth-of-type(3n)")).toHaveLength(0); // No matches for every third a
+            expect(selectAll("#pseudos a:nth-of-type(odd)")).toHaveLength(1); // Found the odd a
+            expect(selectAll("#pseudos a:nth-of-type(1)")).toHaveLength(1); // Found the first a
         });
 
         it(":nth-last-of-type(expr)", () => {
             const second = DomUtils.getElementsByTagName("div", pseudos)[1];
 
             expect(
-                CSSselect.selectAll(
-                    "#pseudos div:nth-last-of-type(3n+1)",
-                    document
-                )
+                selectAll("#pseudos div:nth-last-of-type(3n+1)")
             ).toHaveLength(2); // Found 2 div elements
-            expect(
-                CSSselect.selectAll(
-                    "#pseudos a:nth-last-of-type(3n+1)",
-                    document
-                )
-            ).toHaveLength(1); // Found 1 a element
-            expect(
-                CSSselect.selectAll(
-                    "#pseudos div:nth-last-of-type(5)",
-                    document
-                )[0]
-            ).toBe(second); // 5th nth-last-of-type should be 2nd of 7 elements
+            expect(selectAll("#pseudos a:nth-last-of-type(3n+1)")).toHaveLength(
+                1
+            ); // Found 1 a element
+            expect(selectAll("#pseudos div:nth-last-of-type(5)")[0]).toBe(
+                second
+            ); // 5th nth-last-of-type should be 2nd of 7 elements
         });
 
         it(":first-of-type", () => {
-            expect(
-                CSSselect.selectAll("#pseudos a:first-of-type", document)[0]
-            ).toBe(DomUtils.getElementsByTagName("a", pseudos)[0]); // Found first a element
-            expect(
-                CSSselect.selectAll("#pseudos a:first-of-type", document)
-            ).toHaveLength(1); // Found only 1
+            expect(selectAll("#pseudos a:first-of-type")[0]).toBe(
+                DomUtils.getElementsByTagName("a", pseudos)[0]
+            ); // Found first a element
+            expect(selectAll("#pseudos a:first-of-type")).toHaveLength(1); // Found only 1
         });
 
         it(":last-of-type", () => {
             const all = DomUtils.getElementsByTagName("div", pseudos);
-            expect(
-                CSSselect.selectAll("#pseudos div:last-of-type", document)[0]
-            ).toBe(all[all.length - 1]); // Found last div element
-            expect(
-                CSSselect.selectAll("#pseudos div:last-of-type", document)
-            ).toHaveLength(1); // Found only 1
+            expect(selectAll("#pseudos div:last-of-type")[0]).toBe(
+                all[all.length - 1]
+            ); // Found last div element
+            expect(selectAll("#pseudos div:last-of-type")).toHaveLength(1); // Found only 1
         });
 
         it(":only-of-type", () => {
-            expect(
-                CSSselect.selectAll("#pseudos a:only-of-type", document)[0]
-            ).toBe(DomUtils.getElementsByTagName("a", pseudos)[0]); // Found the only a element
-            expect(
-                CSSselect.selectAll("#pseudos a:first-of-type", document)
-            ).toHaveLength(1); // Found only 1
+            expect(selectAll("#pseudos a:only-of-type")[0]).toBe(
+                DomUtils.getElementsByTagName("a", pseudos)[0]
+            ); // Found the only a element
+            expect(selectAll("#pseudos a:first-of-type")).toHaveLength(1); // Found only 1
         });
 
         it(":target", () => {
             location.hash = "";
-            expect(
-                CSSselect.selectAll("#pseudos:target", document)
-            ).toHaveLength(0); // #pseudos is not the target
+            expect(selectAll("#pseudos:target")).toHaveLength(0); // #pseudos is not the target
             location.hash = "#pseudos";
-            expect(
-                CSSselect.selectAll("#pseudos:target", document)
-            ).toHaveLength(1); // Now #pseudos is the target
+            expect(selectAll("#pseudos:target")).toHaveLength(1); // Now #pseudos is the target
             location.hash = "";
         });
 
         it("custom pseudos", () => {
             // :humanoid implemented just for testing purposes
-            expect(CSSselect.selectAll(":humanoid", document)).toHaveLength(2); // Selected using custom pseudo
+            expect(selectAll(":humanoid")).toHaveLength(2); // Selected using custom pseudo
         });
     });
 
@@ -836,10 +545,7 @@ describe("qwery", () => {
                 CSSselect.is(el, "ol ol li#attr-child-boosh[attr=boosh]")
             ).toBeTruthy(); // Tag tag tag#id[attr=val]
             expect(
-                CSSselect.is(
-                    CSSselect.selectAll("#token-four", document)[0],
-                    "div#fixtures>div a"
-                )
+                CSSselect.is(selectAll("#token-four")[0], "div#fixtures>div a")
             ).toBeTruthy(); // Tag#id>tag tag where ambiguous middle tag requires backtracking
         });
 
@@ -847,34 +553,22 @@ describe("qwery", () => {
             expect(CSSselect.is(el, "li:contains(hello)")).toBe(true); // Matching :contains(text)
             expect(CSSselect.is(el, "li:contains(human)")).toBe(false); // Non-matching :contains(text)
             expect(
-                CSSselect.is(
-                    CSSselect.selectAll("#list>li", document)[2],
-                    ":humanoid"
-                )
+                CSSselect.is(selectAll("#list>li")[2], ":humanoid", options)
             ).toBe(true); // Matching custom pseudo
             expect(
-                CSSselect.is(
-                    CSSselect.selectAll("#list>li", document)[1],
-                    ":humanoid"
-                )
+                CSSselect.is(selectAll("#list>li")[1], ":humanoid", options)
             ).toBe(false); // Non-matching custom pseudo
         });
 
         it("context", () => {
             expect(
                 CSSselect.is(el, "li#attr-child-boosh[attr=boosh]", {
-                    context: CSSselect.selectAll(
-                        "#list",
-                        document
-                    )[0] as Element,
+                    context: selectAll("#list")[0],
                 })
             ).toBeTruthy(); // Context
             expect(
                 CSSselect.is(el, "ol#list li#attr-child-boosh[attr=boosh]", {
-                    context: CSSselect.selectAll(
-                        "#boosh",
-                        document
-                    )[0] as Element,
+                    context: selectAll("#boosh")[0],
                 })
             ).toBeFalsy(); // Wrong context
         });
@@ -882,75 +576,51 @@ describe("qwery", () => {
 
     describe("selecting elements in other documents", () => {
         it("get element by id", () => {
-            const result = CSSselect.selectAll("#hsoob", doc);
+            const result = selectAll("#hsoob", doc);
             expect(result[0]).toBeTruthy(); // Found element with id=hsoob
         });
 
         it("get elements by class", () => {
-            expect(CSSselect.selectAll("#hsoob .a", doc)).toHaveLength(2); // Found two elements
-            expect(CSSselect.selectAll("#hsoob div.a", doc)[0]).toBeTruthy(); // Found one element
-            expect(CSSselect.selectAll("#hsoob div", doc)).toHaveLength(2); // Found two {div} elements
-            expect(CSSselect.selectAll("#hsoob span", doc)[0]).toBeTruthy(); // Found one {span} element
-            expect(CSSselect.selectAll("#hsoob div div", doc)[0]).toBeTruthy(); // Found a single div
-            expect(CSSselect.selectAll("p.odd", doc)).toHaveLength(1); // Found single br
+            expect(selectAll("#hsoob .a", doc)).toHaveLength(2); // Found two elements
+            expect(selectAll("#hsoob div.a", doc)[0]).toBeTruthy(); // Found one element
+            expect(selectAll("#hsoob div", doc)).toHaveLength(2); // Found two {div} elements
+            expect(selectAll("#hsoob span", doc)[0]).toBeTruthy(); // Found one {span} element
+            expect(selectAll("#hsoob div div", doc)[0]).toBeTruthy(); // Found a single div
+            expect(selectAll("p.odd", doc)).toHaveLength(1); // Found single br
         });
 
         it("complex selectors", () => {
-            expect(CSSselect.selectAll(".d ~ .sib", doc)).toHaveLength(2); // Found one ~ sibling
-            expect(CSSselect.selectAll(".a .d + .sib", doc)).toHaveLength(1); // Found 2 + siblings
-            expect(CSSselect.selectAll("#hsoob > div > .h", doc)).toHaveLength(
-                1
-            ); // Found span using child selectors
-            expect(
-                CSSselect.selectAll('.a .d ~ .sib[test="f g"]', doc)
-            ).toHaveLength(1); // Found 1 ~ sibling with test attribute
+            expect(selectAll(".d ~ .sib", doc)).toHaveLength(2); // Found one ~ sibling
+            expect(selectAll(".a .d + .sib", doc)).toHaveLength(1); // Found 2 + siblings
+            expect(selectAll("#hsoob > div > .h", doc)).toHaveLength(1); // Found span using child selectors
+            expect(selectAll('.a .d ~ .sib[test="f g"]', doc)).toHaveLength(1); // Found 1 ~ sibling with test attribute
         });
 
         it("byId sub-queries", () => {
-            expect(CSSselect.selectAll("#hsoob #spanny", doc)).toHaveLength(1); // Found "#id #id" in frame
-            expect(CSSselect.selectAll(".a #spanny", doc)).toHaveLength(1); // Found ".class #id" in frame
-            expect(
-                CSSselect.selectAll(".a #booshTest #spanny", doc)
-            ).toHaveLength(1); // Found ".class #id #id" in frame
-            expect(CSSselect.selectAll("> #hsoob", doc)).toHaveLength(1); // Found "> #id" in frame
+            expect(selectAll("#hsoob #spanny", doc)).toHaveLength(1); // Found "#id #id" in frame
+            expect(selectAll(".a #spanny", doc)).toHaveLength(1); // Found ".class #id" in frame
+            expect(selectAll(".a #booshTest #spanny", doc)).toHaveLength(1); // Found ".class #id #id" in frame
+            expect(selectAll("> #hsoob", doc)).toHaveLength(1); // Found "> #id" in frame
         });
 
         it("byId sub-queries within sub-context", () => {
+            expect(selectAll("#spanny", selectAll("#hsoob", doc))).toHaveLength(
+                1
+            ); // Found "#id -> #id" in frame
             expect(
-                CSSselect.selectAll(
-                    "#spanny",
-                    CSSselect.selectAll("#hsoob", doc)
-                )
-            ).toHaveLength(1); // Found "#id -> #id" in frame
-            expect(
-                CSSselect.selectAll(
-                    ".a #spanny",
-                    CSSselect.selectAll("#hsoob", doc)
-                )
+                selectAll(".a #spanny", selectAll("#hsoob", doc))
             ).toHaveLength(1); // Found ".class #id" in frame
             expect(
-                CSSselect.selectAll(
-                    ".a #booshTest #spanny",
-                    CSSselect.selectAll("#hsoob", doc)
-                )
+                selectAll(".a #booshTest #spanny", selectAll("#hsoob", doc))
             ).toHaveLength(1); // Found ".class #id #id" in frame
             expect(
-                CSSselect.selectAll(
-                    ".a > #booshTest",
-                    CSSselect.selectAll("#hsoob", doc)
-                )
+                selectAll(".a > #booshTest", selectAll("#hsoob", doc))
             ).toHaveLength(1); // Found "> .class #id" in frame
             expect(
-                CSSselect.selectAll(
-                    "#booshTest",
-                    CSSselect.selectAll("#spanny", doc)
-                )
+                selectAll("#booshTest", selectAll("#spanny", doc))
             ).toHaveLength(0); // Shouldn't find #booshTest (ancestor) within #spanny (descendent)
             expect(
-                CSSselect.selectAll(
-                    "#booshTest",
-                    CSSselect.selectAll("#lonelyHsoob", doc)
-                )
+                selectAll("#booshTest", selectAll("#lonelyHsoob", doc))
             ).toHaveLength(0); // Shouldn't find #booshTest within #lonelyHsoob (unrelated)
         });
     });
diff --git a/test/sizzle.ts b/test/sizzle.ts
index 111b3190b6b02dd11abcd88426eb68a44b986cf9..2dd3d7a7c7663de6ae666a078c2e8d1b5417e3d6 100755
--- a/test/sizzle.ts
+++ b/test/sizzle.ts
@@ -1,8 +1,8 @@
 import * as DomUtils from "domutils";
 import * as CSSselect from "../src";
-import type { Element } from "domhandler";
+import type { Element, AnyNode, ParentNode, ChildNode } from "domhandler";
 import { q, t, createWithFriesXML, loadDoc } from "./tools/sizzle-testinit";
-import { parseDOM } from "htmlparser2";
+import { parseDocument, parseDOM } from "htmlparser2";
 let document = loadDoc();
 
 describe("Sizzle", () => {
@@ -30,7 +30,7 @@ describe("Sizzle", () => {
         // Select all
         expect(CSSselect.selectAll("*", document).length >= 30).toBe(true);
         const all = CSSselect.selectAll("*", document);
-        const good = all.every((el) => el.nodeType !== 8);
+        const good = all.every((el: AnyNode) => el.nodeType !== 8);
         // Select all elements, no comment nodes
         expect(good).toBe(true);
         // Element Selector
@@ -128,7 +128,7 @@ describe("Sizzle", () => {
         });
         // Other document as context
         expect(CSSselect.selectAll("p:contains(bar)", iframe)).toStrictEqual([
-            DomUtils.getElementById("foo", iframe.children) as Element,
+            DomUtils.getElementById("foo", iframe.children),
         ]);
         iframe.children = [];
 
@@ -150,7 +150,7 @@ describe("Sizzle", () => {
 
         // Real use case would be using .watch in browsers with window.watch (see Issue #157)
         const elem = document.createElement("toString");
-        elem.attribs.id = "toString";
+        elem.attribs["id"] = "toString";
         DomUtils.appendChild(q("qunit-fixture")[0], elem);
         // Element name matches Object.prototype property
         t("tostring#toString", ["toString"]);
@@ -188,7 +188,7 @@ describe("Sizzle", () => {
         // Check for namespaced element
         expect(
             CSSselect.is(
-                xml.filter((t) => t.type === "tag").pop(),
+                xml.children.filter((t) => t.type === "tag").pop(),
                 "soap\\:Envelope",
                 {
                     xmlMode: true,
@@ -196,7 +196,7 @@ describe("Sizzle", () => {
             )
         ).toBe(true);
 
-        xml = parseDOM(
+        xml = parseDocument(
             "<?xml version='1.0' encoding='UTF-8'?><root><elem id='1'/></root>",
             {
                 xmlMode: true,
@@ -324,7 +324,12 @@ describe("Sizzle", () => {
 
         // ID selector with same value for a name attribute
         expect(
-            (CSSselect.selectOne("#tName1", document) as Element).attribs.id
+            (
+                CSSselect.selectOne<AnyNode, ParentNode>(
+                    "#tName1",
+                    document
+                ) as Element
+            ).attribs["id"]
         ).toBe("tName1");
         // ID selector non-existing but name attribute on an A tag
         t("#tName2", []);
@@ -334,11 +339,15 @@ describe("Sizzle", () => {
         t("#tName1 span", ["tName1-span"]);
         // Ending with ID
         expect(
-            (CSSselect.selectOne("div > div #tName1", document) as Element)
-                .attribs.id
+            (
+                CSSselect.selectOne<AnyNode, ParentNode>(
+                    "div > div #tName1",
+                    document
+                ) as Element
+            ).attribs["id"]
         ).toBe(
             (CSSselect.selectOne("#tName1-span", document)?.parent as Element)
-                .attribs.id
+                .attribs["id"]
         );
 
         parseDOM("<a id='backslash\\foo'></a>").forEach((node) =>
@@ -413,16 +422,14 @@ describe("Sizzle", () => {
             e.parent = div;
         });
         // Finding a second class.
-        expect(CSSselect.selectAll(".e", div)).toStrictEqual([
-            div.children[0] as Element,
-        ]);
+        expect(CSSselect.selectAll(".e", div)).toStrictEqual([div.children[0]]);
 
         const lastChild = div.children[div.children.length - 1] as Element;
-        lastChild.attribs.class = "e";
+        lastChild.attribs["class"] = "e";
 
         // Finding a modified class.
         expect(CSSselect.selectAll(".e", div)).toStrictEqual([
-            div.children[0] as Element,
+            div.children[0],
             lastChild,
         ]);
 
@@ -430,14 +437,14 @@ describe("Sizzle", () => {
         expect(CSSselect.is(div, ".null")).toBe(false);
         // .null does not match an element with no class
         expect(CSSselect.is(div.children[0], ".null div")).toBe(false);
-        div.attribs.class = "null";
+        div.attribs["class"] = "null";
         // .null matches element with class 'null'
         expect(CSSselect.is(div, ".null")).toBe(true);
         // Caching system respects DOM changes
         expect(CSSselect.is(div.children[0], ".null div")).toBe(true);
         // Testing class on document doesn't error
         expect(CSSselect.is(document, ".foo")).toBe(false);
-        lastChild.attribs.class += " hasOwnProperty toString";
+        lastChild.attribs["class"] += " hasOwnProperty toString";
         // Testing class on global object doesn't error
         expect(CSSselect.is(global, ".foo")).toBe(false);
         // Classes match Object.prototype properties
@@ -729,7 +736,7 @@ describe("Sizzle", () => {
         // Attribute Equals Number
         t("#qunit-fixture li[tabIndex=-1]", ["foodWithNegativeTabIndex"]);
 
-        document.getElementById("anchor2").attribs.href = "#2";
+        document.getElementById("anchor2").attribs["href"] = "#2";
         // `href` Attribute
         t("p a[href^=#]", ["anchor2"]);
         t("p a[href*=#]", ["simon1", "anchor2"]);
@@ -803,7 +810,7 @@ describe("Sizzle", () => {
         t("#ap a[hreflang!='en']", ["google", "groups", "anchor1"]);
 
         const opt = document.getElementById("option1a");
-        opt.attribs.test = "";
+        opt.attribs["test"] = "";
 
         // Attribute Is Not Equal Matches
         expect(CSSselect.is(opt, "[id*=option1][type!=checkbox]")).toBe(true);
@@ -838,7 +845,7 @@ describe("Sizzle", () => {
         t("input[name='foo[bar]']", ["hidden2"]);
 
         const input = document.getElementById("text1");
-        input.attribs.title = "Don't click me";
+        input.attribs["title"] = "Don't click me";
 
         // Quote within attribute value does not mess up tokenizer
         expect(CSSselect.is(input, 'input[title="Don\'t click me"]')).toBe(
@@ -931,7 +938,7 @@ describe("Sizzle", () => {
 
         // Finding by attribute with escaped characters.
         expect(CSSselect.selectAll("[xml\\:test]", div)).toStrictEqual([
-            div.children[0] as Element,
+            div.children[0],
         ]);
 
         const foo = document.getElementById("foo");
@@ -939,9 +946,8 @@ describe("Sizzle", () => {
         t("[constructor]", []);
         // Gecko Object.prototype property "watch" (negative)',
         t("[watch]", []);
-        // @ts-expect-error TS doesn't want us to override `constructor`
-        foo.attribs.constructor = "foo";
-        foo.attribs.watch = "bar";
+        foo.attribs["constructor"] = "foo";
+        foo.attribs["watch"] = "bar";
         // Object.prototype property "constructor"',
         t("[constructor='foo']", ["foo"]);
         // Gecko Object.prototype property "watch"',
@@ -1019,10 +1025,13 @@ describe("Sizzle", () => {
         ]);
 
         // Verify that the child position isn't being cached improperly
-        const secondChildren = CSSselect.selectAll("p:nth-child(2)", document);
+        const secondChildren: AnyNode[] = CSSselect.selectAll(
+            "p:nth-child(2)",
+            document
+        );
         const newNodes = secondChildren.map((child) => {
             const [node] = parseDOM("<div></div>");
-            DomUtils.prepend(child, node);
+            DomUtils.prepend(child as ChildNode, node);
             return node;
         });
 
@@ -1373,19 +1382,20 @@ describe("Sizzle", () => {
         t("a:contains((Link))", ["groups"]);
 
         const tmp = document.createElement("div");
-        tmp.attribs.id = "tmp_input";
+        tmp.attribs["id"] = "tmp_input";
         DomUtils.appendChild(document.body, tmp);
 
-        ["button", "submit", "reset"].forEach((type) => {
-            const els = [
-                ...parseDOM(
-                    "<input id='input_%' type='%'/><button id='button_%' type='%'>test</button>".replace(
-                        /%/g,
-                        type
-                    )
-                ),
-            ];
-            els.forEach((el) => DomUtils.appendChild(tmp, el));
+        for (const type of ["button", "submit", "reset"]) {
+            const els = parseDOM(
+                "<input id='input_%' type='%'/><button id='button_%' type='%'>test</button>".replace(
+                    /%/g,
+                    type
+                )
+            ).slice(0); // Create a copy of the array, so that `appendChild` doesn't remove the elements.
+
+            for (const el of els) {
+                DomUtils.appendChild(tmp, el);
+            }
 
             // Input Buttons :${type}
             t(`#tmp_input :${type}`, [`input_${type}`, `button_${type}`]);
@@ -1394,7 +1404,7 @@ describe("Sizzle", () => {
             expect(CSSselect.is(els[0], `:${type}`)).toBe(true);
             // Button Matches :${type}
             expect(CSSselect.is(els[1], `:${type}`)).toBe(true);
-        });
+        }
 
         DomUtils.removeElement(tmp);
 
diff --git a/test/tools/helper.ts b/test/tools/helper.ts
index 338490954a414e2f2695ffb7d1860f20f346c70e..c718eaff6c5628894677204d01b04cb3325c617f 100644
--- a/test/tools/helper.ts
+++ b/test/tools/helper.ts
@@ -1,33 +1,38 @@
 import fs from "fs";
 import path from "path";
-import { parseDOM, ParserOptions, ElementType } from "htmlparser2";
+import { parseDocument, ParserOptions } from "htmlparser2";
 import * as DomUtils from "domutils";
-import { DataNode, Element, Node } from "domhandler";
+import { Text, Element, Document } from "domhandler";
 
-export function getDOMFromPath(file: string, options?: ParserOptions): Node[] {
+export function getDocumentFromPath(
+    file: string,
+    options?: ParserOptions
+): Document {
     const filePath = path.join(__dirname, "..", "fixtures", file);
-    return parseDOM(fs.readFileSync(filePath, "utf8"), options);
+    return parseDocument(fs.readFileSync(filePath, "utf8"), options);
 }
 
-export interface SimpleDocument extends Array<Node> {
+export interface SimpleDocument extends Document {
     getElementById(id: string): Element;
-    createTextNode(content: string): DataNode;
+    createTextNode(content: string): Text;
     createElement(name: string): Element;
     body: Element;
     documentElement: Element;
 }
 
 export function getDocument(file: string): SimpleDocument {
-    const document = getDOMFromPath(file) as SimpleDocument;
+    const document = getDocumentFromPath(file) as SimpleDocument;
 
-    document.getElementById = (id: string) =>
-        DomUtils.getElementById(id, document) as Element;
-    document.createTextNode = (content: string) =>
-        new DataNode(ElementType.Text, content);
+    document.getElementById = (id: string) => {
+        const el = DomUtils.getElementById(id, document.children);
+        if (!el) throw new Error(`Did not find element with ID ${id}`);
+        return el;
+    };
+    document.createTextNode = (content: string) => new Text(content);
     document.createElement = (name: string) =>
-        new Element(name.toLocaleLowerCase(), {});
+        new Element(name.toLowerCase(), {});
     [document.body] = DomUtils.getElementsByTagName("body", document, true, 1);
-    [document.documentElement] = document.filter(DomUtils.isTag);
+    [document.documentElement] = document.children.filter(DomUtils.isTag);
 
     return document;
 }
diff --git a/test/tools/sizzle-testinit.ts b/test/tools/sizzle-testinit.ts
index 255f05983a9255debca41a8b2d6ac215618e30cc..98290c3dcf9aa9a328076a15a654e71abc6fc864 100755
--- a/test/tools/sizzle-testinit.ts
+++ b/test/tools/sizzle-testinit.ts
@@ -1,6 +1,6 @@
-import * as helper from "./helper";
+import * as helper from "./helper.js";
 import CSSselect from "../../src";
-import type { Element, Node } from "domhandler";
+import type { Element, Node, Document } from "domhandler";
 let document = loadDoc();
 
 export function loadDoc(): helper.SimpleDocument {
@@ -30,16 +30,16 @@ export function t(
     context: Node[] | Node | null = document
 ): void {
     const actual = CSSselect(selector, context) as Element[];
-    const actualIds = actual.map((e) => e.attribs.id);
+    const actualIds = actual.map((e) => e.attribs["id"]);
 
     // Should not contain falsy values
     expect(actualIds).toStrictEqual(expectedIds);
 }
 
-const xmlDoc = helper.getDOMFromPath("fries.xml", {
+const xmlDoc = helper.getDocumentFromPath("fries.xml", {
     xmlMode: true,
 });
 
-export function createWithFriesXML(): Node[] {
+export function createWithFriesXML(): Document {
     return xmlDoc;
 }
diff --git a/tsconfig.json b/tsconfig.json
index 5d16dc754c670c9f5d859c9b968d8b93ee389b4d..045b82d54ffff48c3e50880cb73299b7150e8832 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,27 +1,32 @@
 {
     "compilerOptions": {
         /* Basic Options */
-        "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
-        "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
-        // "lib": [],                             /* Specify library files to be included in the compilation. */
-        "declaration": true /* Generates corresponding '.d.ts' file. */,
-        "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
-        // "sourceMap": true,                     /* Generates corresponding '.map' file. */
-        "outDir": "lib" /* Redirect output structure to the directory. */,
-        // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
+        "target": "es5",
+        "module": "commonjs",
+        "lib": ["ES2015.Core"],
+        "declaration": true,
+        "declarationMap": true,
+        "sourceMap": true,
+        "outDir": "lib",
 
         /* Strict Type-Checking Options */
-        "strict": true /* Enable all strict type-checking options. */,
+        "strict": true,
 
         /* Additional Checks */
-        "noUnusedLocals": true /* Report errors on unused locals. */,
-        "noUnusedParameters": true /* Report errors on unused parameters. */,
-        "noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
-        "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
+        "exactOptionalPropertyTypes": true,
+        "forceConsistentCasingInFileNames": true,
+        "importsNotUsedAsValues": "error",
+        "isolatedModules": true,
+        "noFallthroughCasesInSwitch": true,
+        "noImplicitOverride": true,
+        "noImplicitReturns": true,
+        "noPropertyAccessFromIndexSignature": true,
+        "noUnusedLocals": true,
+        "noUnusedParameters": true,
 
         /* Module Resolution Options */
-        // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
-        "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
+        "esModuleInterop": true,
+        "moduleResolution": "node",
         "resolveJsonModule": true
     },
     "include": ["src"],