Index: imaps-frontend/node_modules/fast-uri/.gitattributes
===================================================================
--- imaps-frontend/node_modules/fast-uri/.gitattributes	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/.gitattributes	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,2 @@
+# Set default behavior to automatically convert line endings
+* text=auto eol=lf
Index: imaps-frontend/node_modules/fast-uri/.github/.stale.yml
===================================================================
--- imaps-frontend/node_modules/fast-uri/.github/.stale.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/.github/.stale.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,21 @@
+# Number of days of inactivity before an issue becomes stale
+daysUntilStale: 15
+# Number of days of inactivity before a stale issue is closed
+daysUntilClose: 7
+# Issues with these labels will never be considered stale
+exemptLabels:
+  - "discussion"
+  - "feature request"
+  - "bug"
+  - "help wanted"
+  - "plugin suggestion"
+  - "good first issue"
+# Label to use when marking an issue as stale
+staleLabel: stale
+# Comment to post when marking an issue as stale. Set to `false` to disable
+markComment: >
+  This issue has been automatically marked as stale because it has not had
+  recent activity. It will be closed if no further activity occurs. Thank you
+  for your contributions.
+# Comment to post when closing a stale issue. Set to `false` to disable
+closeComment: false
Index: imaps-frontend/node_modules/fast-uri/.github/dependabot.yml
===================================================================
--- imaps-frontend/node_modules/fast-uri/.github/dependabot.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/.github/dependabot.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,13 @@
+version: 2
+updates:
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "monthly"
+    open-pull-requests-limit: 10
+
+  - package-ecosystem: "npm"
+    directory: "/"
+    schedule:
+      interval: "weekly"
+    open-pull-requests-limit: 10
Index: imaps-frontend/node_modules/fast-uri/.github/tests_checker.yml
===================================================================
--- imaps-frontend/node_modules/fast-uri/.github/tests_checker.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/.github/tests_checker.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,8 @@
+comment: |
+  Hello! Thank you for contributing!
+  It appears that you have changed the code, but the tests that verify your change are missing. Could you please add them?
+fileExtensions:
+  - '.ts'
+  - '.js'
+
+testDir: 'test'
Index: imaps-frontend/node_modules/fast-uri/.github/workflows/ci.yml
===================================================================
--- imaps-frontend/node_modules/fast-uri/.github/workflows/ci.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/.github/workflows/ci.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,58 @@
+name: CI
+
+on:
+  push:
+    branches:
+     - main
+     - master
+     - next
+     - 'v*'
+    paths-ignore:
+      - 'docs/**'
+      - '*.md'
+  pull_request:
+    paths-ignore:
+      - 'docs/**'
+      - '*.md'
+
+jobs:
+  test-regression-check-node10:
+    name: Test compatibility with Node.js 10
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
+
+      - uses: actions/setup-node@v4
+        with:
+          node-version: '10'
+          cache: 'npm'
+          cache-dependency-path: package.json
+          check-latest: true
+
+      - name: Install
+        run: |
+          npm install --ignore-scripts
+
+      - name: Copy project as fast-uri to node_node_modules
+        run: |
+          rm -rf ./node_modules/fast-uri/lib &&
+          rm -rf ./node_modules/fast-uri/index.js &&
+          cp -r ./lib ./node_modules/fast-uri/lib &&
+          cp ./index.js ./node_modules/fast-uri/index.js
+
+      - name: Run tests
+        run: |
+          npm run test:unit
+        env:
+          NODE_OPTIONS: no-network-family-autoselection
+
+  test:
+    needs:
+      - test-regression-check-node10
+    uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5
+    with:
+      license-check: true
+      lint: true
+      node-versions: '["16", "18", "20", "22"]'
Index: imaps-frontend/node_modules/fast-uri/.github/workflows/package-manager-ci.yml
===================================================================
--- imaps-frontend/node_modules/fast-uri/.github/workflows/package-manager-ci.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/.github/workflows/package-manager-ci.yml	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,20 @@
+name: package-manager-ci
+
+on:
+  push:
+    branches:
+     - main
+     - master
+     - next
+     - 'v*'
+    paths-ignore:
+      - 'docs/**'
+      - '*.md'
+  pull_request:
+    paths-ignore:
+      - 'docs/**'
+      - '*.md'
+
+jobs:
+  test:
+    uses: fastify/workflows/.github/workflows/plugins-ci-package-manager.yml@v5
Index: imaps-frontend/node_modules/fast-uri/LICENSE
===================================================================
--- imaps-frontend/node_modules/fast-uri/LICENSE	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/LICENSE	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,30 @@
+Copyright (c) 2021 The Fastify Team
+Copyright (c) 2011-2021, Gary Court until https://github.com/garycourt/uri-js/commit/a1acf730b4bba3f1097c9f52e7d9d3aba8cdcaae
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * The names of any contributors may not be used to endorse or promote
+      products derived from this software without specific prior written
+      permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+                                  *   *   *
+
+The complete list of contributors can be found at:
+- https://github.com/garycourt/uri-js/graphs/contributors
Index: imaps-frontend/node_modules/fast-uri/README.md
===================================================================
--- imaps-frontend/node_modules/fast-uri/README.md	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/README.md	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,130 @@
+# fast-uri
+
+<div align="center">
+
+[![NPM version](https://img.shields.io/npm/v/fast-uri.svg?style=flat)](https://www.npmjs.com/package/fast-uri)
+[![CI](https://github.com/fastify/fast-uri/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/fastify/fast-uri/actions/workflows/ci.yml)
+[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)
+
+</div>
+
+Dependency-free RFC 3986 URI toolbox.
+
+## Usage
+
+## Options
+
+All of the above functions can accept an additional options argument that is an object that can contain one or more of the following properties:
+
+*	`scheme` (string)
+	Indicates the scheme that the URI should be treated as, overriding the URI's normal scheme parsing behavior.
+
+*	`reference` (string)
+	If set to `"suffix"`, it indicates that the URI is in the suffix format and the parser will use the option's `scheme` property to determine the URI's scheme.
+
+*	`tolerant` (boolean, false)
+	If set to `true`, the parser will relax URI resolving rules.
+
+*	`absolutePath` (boolean, false)
+	If set to `true`, the serializer will not resolve a relative `path` component.
+
+*	`unicodeSupport` (boolean, false)
+	If set to `true`, the parser will unescape non-ASCII characters in the parsed output as per [RFC 3987](http://www.ietf.org/rfc/rfc3987.txt).
+
+*	`domainHost` (boolean, false)
+	If set to `true`, the library will treat the `host` component as a domain name, and convert IDNs (International Domain Names) as per [RFC 5891](http://www.ietf.org/rfc/rfc5891.txt).
+
+### Parse
+
+```js
+const uri = require('fast-uri')
+uri.parse('uri://user:pass@example.com:123/one/two.three?q1=a1&q2=a2#body')
+// Output
+{
+  scheme: "uri",
+  userinfo: "user:pass",
+  host: "example.com",
+  port: 123,
+  path: "/one/two.three",
+  query: "q1=a1&q2=a2",
+  fragment: "body"
+}
+```
+
+### Serialize
+
+```js
+const uri = require('fast-uri')
+uri.serialize({scheme: "http", host: "example.com", fragment: "footer"})
+// Output
+"http://example.com/#footer"
+
+```
+
+### Resolve
+
+```js
+const uri = require('fast-uri')
+uri.resolve("uri://a/b/c/d?q", "../../g")
+// Output
+"uri://a/g"
+```
+
+### Equal
+
+```js
+const uri = require('fast-uri')
+uri.equal("example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7bfoo%7d")
+// Output
+true
+```
+
+## Scheme supports
+
+fast-uri supports inserting custom [scheme](http://en.wikipedia.org/wiki/URI_scheme)-dependent processing rules. Currently, fast-uri has built-in support for the following schemes:
+
+*	http \[[RFC 2616](http://www.ietf.org/rfc/rfc2616.txt)\]
+*	https \[[RFC 2818](http://www.ietf.org/rfc/rfc2818.txt)\]
+*	ws \[[RFC 6455](http://www.ietf.org/rfc/rfc6455.txt)\]
+*	wss \[[RFC 6455](http://www.ietf.org/rfc/rfc6455.txt)\]
+*	urn \[[RFC 2141](http://www.ietf.org/rfc/rfc2141.txt)\]
+*	urn:uuid \[[RFC 4122](http://www.ietf.org/rfc/rfc4122.txt)\]
+
+
+## Benchmarks
+
+```
+fast-uri: parse domain x 1,306,864 ops/sec ±0.31% (100 runs sampled)
+urijs: parse domain x 483,001 ops/sec ±0.09% (99 runs sampled)
+WHATWG URL: parse domain x 862,461 ops/sec ±0.18% (97 runs sampled)
+fast-uri: parse IPv4 x 2,381,452 ops/sec ±0.26% (96 runs sampled)
+urijs: parse IPv4 x 384,705 ops/sec ±0.34% (99 runs sampled)
+WHATWG URL: parse IPv4 NOT SUPPORTED
+fast-uri: parse IPv6 x 923,519 ops/sec ±0.09% (100 runs sampled)
+urijs: parse IPv6 x 289,070 ops/sec ±0.07% (95 runs sampled)
+WHATWG URL: parse IPv6 NOT SUPPORTED
+fast-uri: parse URN x 2,596,395 ops/sec ±0.42% (98 runs sampled)
+urijs: parse URN x 1,152,412 ops/sec ±0.09% (97 runs sampled)
+WHATWG URL: parse URN x 1,183,307 ops/sec ±0.38% (100 runs sampled)
+fast-uri: parse URN uuid x 1,666,861 ops/sec ±0.10% (98 runs sampled)
+urijs: parse URN uuid x 852,724 ops/sec ±0.17% (95 runs sampled)
+WHATWG URL: parse URN uuid NOT SUPPORTED
+fast-uri: serialize uri x 1,741,499 ops/sec ±0.57% (95 runs sampled)
+urijs: serialize uri x 389,014 ops/sec ±0.28% (93 runs sampled)
+fast-uri: serialize IPv6 x 441,095 ops/sec ±0.37% (97 runs sampled)
+urijs: serialize IPv6 x 255,443 ops/sec ±0.58% (94 runs sampled)
+fast-uri: serialize ws x 1,448,667 ops/sec ±0.25% (97 runs sampled)
+urijs: serialize ws x 352,884 ops/sec ±0.08% (96 runs sampled)
+fast-uri: resolve x 340,084 ops/sec ±0.98% (98 runs sampled)
+urijs: resolve x 225,759 ops/sec ±0.37% (95 runs sampled)
+```
+
+## TODO
+
+- [ ] Support MailTo
+- [ ] Be 100% iso compatible with uri-js
+- [ ] Add browser test stack
+
+## License
+
+Licensed under [BSD-3-Clause](./LICENSE).
Index: imaps-frontend/node_modules/fast-uri/benchmark.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/benchmark.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/benchmark.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,105 @@
+'use strict'
+
+const benchmark = require('benchmark')
+const suite = new benchmark.Suite()
+const fasturi = require('./')
+const urijs = require('uri-js')
+
+const base = 'uri://a/b/c/d;p?q'
+
+const domain = 'https://example.com/foo#bar$fiz'
+const ipv4 = '//10.10.10.10'
+const ipv6 = '//[2001:db8::7]'
+const urn = 'urn:foo:a123,456'
+const urnuuid = 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6'
+
+// Initialization as there is a lot to parse at first
+// eg: regexes
+fasturi.parse(domain)
+urijs.parse(domain)
+
+suite.add('fast-uri: parse domain', function () {
+  fasturi.parse(domain)
+})
+suite.add('urijs: parse domain', function () {
+  urijs.parse(domain)
+})
+suite.add('WHATWG URL: parse domain', function () {
+  // eslint-disable-next-line
+  new URL(domain)
+})
+suite.add('fast-uri: parse IPv4', function () {
+  fasturi.parse(ipv4)
+})
+suite.add('urijs: parse IPv4', function () {
+  urijs.parse(ipv4)
+})
+suite.add('fast-uri: parse IPv6', function () {
+  fasturi.parse(ipv6)
+})
+suite.add('urijs: parse IPv6', function () {
+  urijs.parse(ipv6)
+})
+suite.add('fast-uri: parse URN', function () {
+  fasturi.parse(urn)
+})
+suite.add('urijs: parse URN', function () {
+  urijs.parse(urn)
+})
+suite.add('WHATWG URL: parse URN', function () {
+  // eslint-disable-next-line
+  new URL(urn)
+})
+suite.add('fast-uri: parse URN uuid', function () {
+  fasturi.parse(urnuuid)
+})
+suite.add('urijs: parse URN uuid', function () {
+  urijs.parse(urnuuid)
+})
+suite.add('fast-uri: serialize uri', function () {
+  fasturi.serialize({
+    scheme: 'uri',
+    userinfo: 'foo:bar',
+    host: 'example.com',
+    port: 1,
+    path: 'path',
+    query: 'query',
+    fragment: 'fragment'
+  })
+})
+suite.add('urijs: serialize uri', function () {
+  urijs.serialize({
+    scheme: 'uri',
+    userinfo: 'foo:bar',
+    host: 'example.com',
+    port: 1,
+    path: 'path',
+    query: 'query',
+    fragment: 'fragment'
+  })
+})
+suite.add('fast-uri: serialize IPv6', function () {
+  fasturi.serialize({ host: '2606:2800:220:1:248:1893:25c8:1946' })
+})
+suite.add('urijs: serialize IPv6', function () {
+  urijs.serialize({ host: '2606:2800:220:1:248:1893:25c8:1946' })
+})
+suite.add('fast-uri: serialize ws', function () {
+  fasturi.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: true })
+})
+suite.add('urijs: serialize ws', function () {
+  urijs.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: true })
+})
+suite.add('fast-uri: resolve', function () {
+  fasturi.resolve(base, '../../../g')
+})
+suite.add('urijs: resolve', function () {
+  urijs.resolve(base, '../../../g')
+})
+suite.on('cycle', cycle)
+
+suite.run()
+
+function cycle (e) {
+  console.log(e.target.toString())
+}
Index: imaps-frontend/node_modules/fast-uri/eslint.config.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/eslint.config.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/eslint.config.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,6 @@
+'use strict'
+
+module.exports = require('neostandard')({
+  ignores: require('neostandard').resolveIgnoresFromGitignore(),
+  ts: true
+})
Index: imaps-frontend/node_modules/fast-uri/index.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/index.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/index.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,303 @@
+'use strict'
+
+const { normalizeIPv6, normalizeIPv4, removeDotSegments, recomposeAuthority, normalizeComponentEncoding } = require('./lib/utils')
+const SCHEMES = require('./lib/schemes')
+
+function normalize (uri, options) {
+  if (typeof uri === 'string') {
+    uri = serialize(parse(uri, options), options)
+  } else if (typeof uri === 'object') {
+    uri = parse(serialize(uri, options), options)
+  }
+  return uri
+}
+
+function resolve (baseURI, relativeURI, options) {
+  const schemelessOptions = Object.assign({ scheme: 'null' }, options)
+  const resolved = resolveComponents(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true)
+  return serialize(resolved, { ...schemelessOptions, skipEscape: true })
+}
+
+function resolveComponents (base, relative, options, skipNormalization) {
+  const target = {}
+  if (!skipNormalization) {
+    base = parse(serialize(base, options), options) // normalize base components
+    relative = parse(serialize(relative, options), options) // normalize relative components
+  }
+  options = options || {}
+
+  if (!options.tolerant && relative.scheme) {
+    target.scheme = relative.scheme
+    // target.authority = relative.authority;
+    target.userinfo = relative.userinfo
+    target.host = relative.host
+    target.port = relative.port
+    target.path = removeDotSegments(relative.path || '')
+    target.query = relative.query
+  } else {
+    if (relative.userinfo !== undefined || relative.host !== undefined || relative.port !== undefined) {
+      // target.authority = relative.authority;
+      target.userinfo = relative.userinfo
+      target.host = relative.host
+      target.port = relative.port
+      target.path = removeDotSegments(relative.path || '')
+      target.query = relative.query
+    } else {
+      if (!relative.path) {
+        target.path = base.path
+        if (relative.query !== undefined) {
+          target.query = relative.query
+        } else {
+          target.query = base.query
+        }
+      } else {
+        if (relative.path.charAt(0) === '/') {
+          target.path = removeDotSegments(relative.path)
+        } else {
+          if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
+            target.path = '/' + relative.path
+          } else if (!base.path) {
+            target.path = relative.path
+          } else {
+            target.path = base.path.slice(0, base.path.lastIndexOf('/') + 1) + relative.path
+          }
+          target.path = removeDotSegments(target.path)
+        }
+        target.query = relative.query
+      }
+      // target.authority = base.authority;
+      target.userinfo = base.userinfo
+      target.host = base.host
+      target.port = base.port
+    }
+    target.scheme = base.scheme
+  }
+
+  target.fragment = relative.fragment
+
+  return target
+}
+
+function equal (uriA, uriB, options) {
+  if (typeof uriA === 'string') {
+    uriA = unescape(uriA)
+    uriA = serialize(normalizeComponentEncoding(parse(uriA, options), true), { ...options, skipEscape: true })
+  } else if (typeof uriA === 'object') {
+    uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true })
+  }
+
+  if (typeof uriB === 'string') {
+    uriB = unescape(uriB)
+    uriB = serialize(normalizeComponentEncoding(parse(uriB, options), true), { ...options, skipEscape: true })
+  } else if (typeof uriB === 'object') {
+    uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true })
+  }
+
+  return uriA.toLowerCase() === uriB.toLowerCase()
+}
+
+function serialize (cmpts, opts) {
+  const components = {
+    host: cmpts.host,
+    scheme: cmpts.scheme,
+    userinfo: cmpts.userinfo,
+    port: cmpts.port,
+    path: cmpts.path,
+    query: cmpts.query,
+    nid: cmpts.nid,
+    nss: cmpts.nss,
+    uuid: cmpts.uuid,
+    fragment: cmpts.fragment,
+    reference: cmpts.reference,
+    resourceName: cmpts.resourceName,
+    secure: cmpts.secure,
+    error: ''
+  }
+  const options = Object.assign({}, opts)
+  const uriTokens = []
+
+  // find scheme handler
+  const schemeHandler = SCHEMES[(options.scheme || components.scheme || '').toLowerCase()]
+
+  // perform scheme specific serialization
+  if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(components, options)
+
+  if (components.path !== undefined) {
+    if (!options.skipEscape) {
+      components.path = escape(components.path)
+
+      if (components.scheme !== undefined) {
+        components.path = components.path.split('%3A').join(':')
+      }
+    } else {
+      components.path = unescape(components.path)
+    }
+  }
+
+  if (options.reference !== 'suffix' && components.scheme) {
+    uriTokens.push(components.scheme, ':')
+  }
+
+  const authority = recomposeAuthority(components)
+  if (authority !== undefined) {
+    if (options.reference !== 'suffix') {
+      uriTokens.push('//')
+    }
+
+    uriTokens.push(authority)
+
+    if (components.path && components.path.charAt(0) !== '/') {
+      uriTokens.push('/')
+    }
+  }
+  if (components.path !== undefined) {
+    let s = components.path
+
+    if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
+      s = removeDotSegments(s)
+    }
+
+    if (authority === undefined) {
+      s = s.replace(/^\/\//u, '/%2F') // don't allow the path to start with "//"
+    }
+
+    uriTokens.push(s)
+  }
+
+  if (components.query !== undefined) {
+    uriTokens.push('?', components.query)
+  }
+
+  if (components.fragment !== undefined) {
+    uriTokens.push('#', components.fragment)
+  }
+  return uriTokens.join('')
+}
+
+const hexLookUp = Array.from({ length: 127 }, (_v, k) => /[^!"$&'()*+,\-.;=_`a-z{}~]/u.test(String.fromCharCode(k)))
+
+function nonSimpleDomain (value) {
+  let code = 0
+  for (let i = 0, len = value.length; i < len; ++i) {
+    code = value.charCodeAt(i)
+    if (code > 126 || hexLookUp[code]) {
+      return true
+    }
+  }
+  return false
+}
+
+const URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u
+
+function parse (uri, opts) {
+  const options = Object.assign({}, opts)
+  const parsed = {
+    scheme: undefined,
+    userinfo: undefined,
+    host: '',
+    port: undefined,
+    path: '',
+    query: undefined,
+    fragment: undefined
+  }
+  const gotEncoding = uri.indexOf('%') !== -1
+  let isIP = false
+  if (options.reference === 'suffix') uri = (options.scheme ? options.scheme + ':' : '') + '//' + uri
+
+  const matches = uri.match(URI_PARSE)
+
+  if (matches) {
+    // store each component
+    parsed.scheme = matches[1]
+    parsed.userinfo = matches[3]
+    parsed.host = matches[4]
+    parsed.port = parseInt(matches[5], 10)
+    parsed.path = matches[6] || ''
+    parsed.query = matches[7]
+    parsed.fragment = matches[8]
+
+    // fix port number
+    if (isNaN(parsed.port)) {
+      parsed.port = matches[5]
+    }
+    if (parsed.host) {
+      const ipv4result = normalizeIPv4(parsed.host)
+      if (ipv4result.isIPV4 === false) {
+        const ipv6result = normalizeIPv6(ipv4result.host)
+        parsed.host = ipv6result.host.toLowerCase()
+        isIP = ipv6result.isIPV6
+      } else {
+        parsed.host = ipv4result.host
+        isIP = true
+      }
+    }
+    if (parsed.scheme === undefined && parsed.userinfo === undefined && parsed.host === undefined && parsed.port === undefined && !parsed.path && parsed.query === undefined) {
+      parsed.reference = 'same-document'
+    } else if (parsed.scheme === undefined) {
+      parsed.reference = 'relative'
+    } else if (parsed.fragment === undefined) {
+      parsed.reference = 'absolute'
+    } else {
+      parsed.reference = 'uri'
+    }
+
+    // check for reference errors
+    if (options.reference && options.reference !== 'suffix' && options.reference !== parsed.reference) {
+      parsed.error = parsed.error || 'URI is not a ' + options.reference + ' reference.'
+    }
+
+    // find scheme handler
+    const schemeHandler = SCHEMES[(options.scheme || parsed.scheme || '').toLowerCase()]
+
+    // check if scheme can't handle IRIs
+    if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
+      // if host component is a domain name
+      if (parsed.host && (options.domainHost || (schemeHandler && schemeHandler.domainHost)) && isIP === false && nonSimpleDomain(parsed.host)) {
+        // convert Unicode IDN -> ASCII IDN
+        try {
+          parsed.host = URL.domainToASCII(parsed.host.toLowerCase())
+        } catch (e) {
+          parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e
+        }
+      }
+      // convert IRI -> URI
+    }
+
+    if (!schemeHandler || (schemeHandler && !schemeHandler.skipNormalize)) {
+      if (gotEncoding && parsed.scheme !== undefined) {
+        parsed.scheme = unescape(parsed.scheme)
+      }
+      if (gotEncoding && parsed.host !== undefined) {
+        parsed.host = unescape(parsed.host)
+      }
+      if (parsed.path && parsed.path.length) {
+        parsed.path = escape(unescape(parsed.path))
+      }
+      if (parsed.fragment && parsed.fragment.length) {
+        parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment))
+      }
+    }
+
+    // perform scheme specific parsing
+    if (schemeHandler && schemeHandler.parse) {
+      schemeHandler.parse(parsed, options)
+    }
+  } else {
+    parsed.error = parsed.error || 'URI can not be parsed.'
+  }
+  return parsed
+}
+
+const fastUri = {
+  SCHEMES,
+  normalize,
+  resolve,
+  resolveComponents,
+  equal,
+  serialize,
+  parse
+}
+
+module.exports = fastUri
+module.exports.default = fastUri
+module.exports.fastUri = fastUri
Index: imaps-frontend/node_modules/fast-uri/lib/schemes.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/lib/schemes.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/lib/schemes.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,188 @@
+'use strict'
+
+const UUID_REG = /^[\da-f]{8}\b-[\da-f]{4}\b-[\da-f]{4}\b-[\da-f]{4}\b-[\da-f]{12}$/iu
+const URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu
+
+function isSecure (wsComponents) {
+  return typeof wsComponents.secure === 'boolean' ? wsComponents.secure : String(wsComponents.scheme).toLowerCase() === 'wss'
+}
+
+function httpParse (components) {
+  if (!components.host) {
+    components.error = components.error || 'HTTP URIs must have a host.'
+  }
+
+  return components
+}
+
+function httpSerialize (components) {
+  const secure = String(components.scheme).toLowerCase() === 'https'
+
+  // normalize the default port
+  if (components.port === (secure ? 443 : 80) || components.port === '') {
+    components.port = undefined
+  }
+
+  // normalize the empty path
+  if (!components.path) {
+    components.path = '/'
+  }
+
+  // NOTE: We do not parse query strings for HTTP URIs
+  // as WWW Form Url Encoded query strings are part of the HTML4+ spec,
+  // and not the HTTP spec.
+
+  return components
+}
+
+function wsParse (wsComponents) {
+// indicate if the secure flag is set
+  wsComponents.secure = isSecure(wsComponents)
+
+  // construct resouce name
+  wsComponents.resourceName = (wsComponents.path || '/') + (wsComponents.query ? '?' + wsComponents.query : '')
+  wsComponents.path = undefined
+  wsComponents.query = undefined
+
+  return wsComponents
+}
+
+function wsSerialize (wsComponents) {
+// normalize the default port
+  if (wsComponents.port === (isSecure(wsComponents) ? 443 : 80) || wsComponents.port === '') {
+    wsComponents.port = undefined
+  }
+
+  // ensure scheme matches secure flag
+  if (typeof wsComponents.secure === 'boolean') {
+    wsComponents.scheme = (wsComponents.secure ? 'wss' : 'ws')
+    wsComponents.secure = undefined
+  }
+
+  // reconstruct path from resource name
+  if (wsComponents.resourceName) {
+    const [path, query] = wsComponents.resourceName.split('?')
+    wsComponents.path = (path && path !== '/' ? path : undefined)
+    wsComponents.query = query
+    wsComponents.resourceName = undefined
+  }
+
+  // forbid fragment component
+  wsComponents.fragment = undefined
+
+  return wsComponents
+}
+
+function urnParse (urnComponents, options) {
+  if (!urnComponents.path) {
+    urnComponents.error = 'URN can not be parsed'
+    return urnComponents
+  }
+  const matches = urnComponents.path.match(URN_REG)
+  if (matches) {
+    const scheme = options.scheme || urnComponents.scheme || 'urn'
+    urnComponents.nid = matches[1].toLowerCase()
+    urnComponents.nss = matches[2]
+    const urnScheme = `${scheme}:${options.nid || urnComponents.nid}`
+    const schemeHandler = SCHEMES[urnScheme]
+    urnComponents.path = undefined
+
+    if (schemeHandler) {
+      urnComponents = schemeHandler.parse(urnComponents, options)
+    }
+  } else {
+    urnComponents.error = urnComponents.error || 'URN can not be parsed.'
+  }
+
+  return urnComponents
+}
+
+function urnSerialize (urnComponents, options) {
+  const scheme = options.scheme || urnComponents.scheme || 'urn'
+  const nid = urnComponents.nid.toLowerCase()
+  const urnScheme = `${scheme}:${options.nid || nid}`
+  const schemeHandler = SCHEMES[urnScheme]
+
+  if (schemeHandler) {
+    urnComponents = schemeHandler.serialize(urnComponents, options)
+  }
+
+  const uriComponents = urnComponents
+  const nss = urnComponents.nss
+  uriComponents.path = `${nid || options.nid}:${nss}`
+
+  options.skipEscape = true
+  return uriComponents
+}
+
+function urnuuidParse (urnComponents, options) {
+  const uuidComponents = urnComponents
+  uuidComponents.uuid = uuidComponents.nss
+  uuidComponents.nss = undefined
+
+  if (!options.tolerant && (!uuidComponents.uuid || !UUID_REG.test(uuidComponents.uuid))) {
+    uuidComponents.error = uuidComponents.error || 'UUID is not valid.'
+  }
+
+  return uuidComponents
+}
+
+function urnuuidSerialize (uuidComponents) {
+  const urnComponents = uuidComponents
+  // normalize UUID
+  urnComponents.nss = (uuidComponents.uuid || '').toLowerCase()
+  return urnComponents
+}
+
+const http = {
+  scheme: 'http',
+  domainHost: true,
+  parse: httpParse,
+  serialize: httpSerialize
+}
+
+const https = {
+  scheme: 'https',
+  domainHost: http.domainHost,
+  parse: httpParse,
+  serialize: httpSerialize
+}
+
+const ws = {
+  scheme: 'ws',
+  domainHost: true,
+  parse: wsParse,
+  serialize: wsSerialize
+}
+
+const wss = {
+  scheme: 'wss',
+  domainHost: ws.domainHost,
+  parse: ws.parse,
+  serialize: ws.serialize
+}
+
+const urn = {
+  scheme: 'urn',
+  parse: urnParse,
+  serialize: urnSerialize,
+  skipNormalize: true
+}
+
+const urnuuid = {
+  scheme: 'urn:uuid',
+  parse: urnuuidParse,
+  serialize: urnuuidSerialize,
+  skipNormalize: true
+}
+
+const SCHEMES = {
+  http,
+  https,
+  ws,
+  wss,
+  urn,
+  'urn:uuid': urnuuid
+}
+
+module.exports = SCHEMES
Index: imaps-frontend/node_modules/fast-uri/lib/scopedChars.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/lib/scopedChars.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/lib/scopedChars.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,30 @@
+'use strict'
+
+const HEX = {
+  0: 0,
+  1: 1,
+  2: 2,
+  3: 3,
+  4: 4,
+  5: 5,
+  6: 6,
+  7: 7,
+  8: 8,
+  9: 9,
+  a: 10,
+  A: 10,
+  b: 11,
+  B: 11,
+  c: 12,
+  C: 12,
+  d: 13,
+  D: 13,
+  e: 14,
+  E: 14,
+  f: 15,
+  F: 15
+}
+
+module.exports = {
+  HEX
+}
Index: imaps-frontend/node_modules/fast-uri/lib/utils.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/lib/utils.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/lib/utils.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,244 @@
+'use strict'
+
+const { HEX } = require('./scopedChars')
+
+const IPV4_REG = /^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u
+
+function normalizeIPv4 (host) {
+  if (findToken(host, '.') < 3) { return { host, isIPV4: false } }
+  const matches = host.match(IPV4_REG) || []
+  const [address] = matches
+  if (address) {
+    return { host: stripLeadingZeros(address, '.'), isIPV4: true }
+  } else {
+    return { host, isIPV4: false }
+  }
+}
+
+/**
+ * @param {string[]} input
+ * @param {boolean} [keepZero=false]
+ * @returns {string|undefined}
+ */
+function stringArrayToHexStripped (input, keepZero = false) {
+  let acc = ''
+  let strip = true
+  for (const c of input) {
+    if (HEX[c] === undefined) return undefined
+    if (c !== '0' && strip === true) strip = false
+    if (!strip) acc += c
+  }
+  if (keepZero && acc.length === 0) acc = '0'
+  return acc
+}
+
+function getIPV6 (input) {
+  let tokenCount = 0
+  const output = { error: false, address: '', zone: '' }
+  const address = []
+  const buffer = []
+  let isZone = false
+  let endipv6Encountered = false
+  let endIpv6 = false
+
+  function consume () {
+    if (buffer.length) {
+      if (isZone === false) {
+        const hex = stringArrayToHexStripped(buffer)
+        if (hex !== undefined) {
+          address.push(hex)
+        } else {
+          output.error = true
+          return false
+        }
+      }
+      buffer.length = 0
+    }
+    return true
+  }
+
+  for (let i = 0; i < input.length; i++) {
+    const cursor = input[i]
+    if (cursor === '[' || cursor === ']') { continue }
+    if (cursor === ':') {
+      if (endipv6Encountered === true) {
+        endIpv6 = true
+      }
+      if (!consume()) { break }
+      tokenCount++
+      address.push(':')
+      if (tokenCount > 7) {
+        // not valid
+        output.error = true
+        break
+      }
+      if (i - 1 >= 0 && input[i - 1] === ':') {
+        endipv6Encountered = true
+      }
+      continue
+    } else if (cursor === '%') {
+      if (!consume()) { break }
+      // switch to zone detection
+      isZone = true
+    } else {
+      buffer.push(cursor)
+      continue
+    }
+  }
+  if (buffer.length) {
+    if (isZone) {
+      output.zone = buffer.join('')
+    } else if (endIpv6) {
+      address.push(buffer.join(''))
+    } else {
+      address.push(stringArrayToHexStripped(buffer))
+    }
+  }
+  output.address = address.join('')
+  return output
+}
+
+function normalizeIPv6 (host) {
+  if (findToken(host, ':') < 2) { return { host, isIPV6: false } }
+  const ipv6 = getIPV6(host)
+
+  if (!ipv6.error) {
+    let newHost = ipv6.address
+    let escapedHost = ipv6.address
+    if (ipv6.zone) {
+      newHost += '%' + ipv6.zone
+      escapedHost += '%25' + ipv6.zone
+    }
+    return { host: newHost, escapedHost, isIPV6: true }
+  } else {
+    return { host, isIPV6: false }
+  }
+}
+
+function stripLeadingZeros (str, token) {
+  let out = ''
+  let skip = true
+  const l = str.length
+  for (let i = 0; i < l; i++) {
+    const c = str[i]
+    if (c === '0' && skip) {
+      if ((i + 1 <= l && str[i + 1] === token) || i + 1 === l) {
+        out += c
+        skip = false
+      }
+    } else {
+      if (c === token) {
+        skip = true
+      } else {
+        skip = false
+      }
+      out += c
+    }
+  }
+  return out
+}
+
+function findToken (str, token) {
+  let ind = 0
+  for (let i = 0; i < str.length; i++) {
+    if (str[i] === token) ind++
+  }
+  return ind
+}
+
+const RDS1 = /^\.\.?\//u
+const RDS2 = /^\/\.(?:\/|$)/u
+const RDS3 = /^\/\.\.(?:\/|$)/u
+const RDS5 = /^\/?(?:.|\n)*?(?=\/|$)/u
+
+function removeDotSegments (input) {
+  const output = []
+
+  while (input.length) {
+    if (input.match(RDS1)) {
+      input = input.replace(RDS1, '')
+    } else if (input.match(RDS2)) {
+      input = input.replace(RDS2, '/')
+    } else if (input.match(RDS3)) {
+      input = input.replace(RDS3, '/')
+      output.pop()
+    } else if (input === '.' || input === '..') {
+      input = ''
+    } else {
+      const im = input.match(RDS5)
+      if (im) {
+        const s = im[0]
+        input = input.slice(s.length)
+        output.push(s)
+      } else {
+        throw new Error('Unexpected dot segment condition')
+      }
+    }
+  }
+  return output.join('')
+}
+
+function normalizeComponentEncoding (components, esc) {
+  const func = esc !== true ? escape : unescape
+  if (components.scheme !== undefined) {
+    components.scheme = func(components.scheme)
+  }
+  if (components.userinfo !== undefined) {
+    components.userinfo = func(components.userinfo)
+  }
+  if (components.host !== undefined) {
+    components.host = func(components.host)
+  }
+  if (components.path !== undefined) {
+    components.path = func(components.path)
+  }
+  if (components.query !== undefined) {
+    components.query = func(components.query)
+  }
+  if (components.fragment !== undefined) {
+    components.fragment = func(components.fragment)
+  }
+  return components
+}
+
+function recomposeAuthority (components) {
+  const uriTokens = []
+
+  if (components.userinfo !== undefined) {
+    uriTokens.push(components.userinfo)
+    uriTokens.push('@')
+  }
+
+  if (components.host !== undefined) {
+    let host = unescape(components.host)
+    const ipV4res = normalizeIPv4(host)
+
+    if (ipV4res.isIPV4) {
+      host = ipV4res.host
+    } else {
+      const ipV6res = normalizeIPv6(ipV4res.host)
+      if (ipV6res.isIPV6 === true) {
+        host = `[${ipV6res.escapedHost}]`
+      } else {
+        host = components.host
+      }
+    }
+    uriTokens.push(host)
+  }
+
+  if (typeof components.port === 'number' || typeof components.port === 'string') {
+    uriTokens.push(':')
+    uriTokens.push(String(components.port))
+  }
+
+  return uriTokens.length ? uriTokens.join('') : undefined
+};
+
+module.exports = {
+  recomposeAuthority,
+  normalizeComponentEncoding,
+  removeDotSegments,
+  normalizeIPv4,
+  normalizeIPv6,
+  stringArrayToHexStripped
+}
Index: imaps-frontend/node_modules/fast-uri/package.json
===================================================================
--- imaps-frontend/node_modules/fast-uri/package.json	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/package.json	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,98 @@
+{
+  "_from": "fast-uri@^3.0.1",
+  "_id": "fast-uri@3.0.5",
+  "_inBundle": false,
+  "_integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==",
+  "_location": "/fast-uri",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "range",
+    "registry": true,
+    "raw": "fast-uri@^3.0.1",
+    "name": "fast-uri",
+    "escapedName": "fast-uri",
+    "rawSpec": "^3.0.1",
+    "saveSpec": null,
+    "fetchSpec": "^3.0.1"
+  },
+  "_requiredBy": [
+    "/ajv-formats/ajv",
+    "/schema-utils/ajv"
+  ],
+  "_resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz",
+  "_shasum": "19f5f9691d0dab9b85861a7bb5d98fca961da9cd",
+  "_spec": "fast-uri@^3.0.1",
+  "_where": "/home/stevetosak/Proekt/IMaps/imaps-frontend/node_modules/schema-utils/node_modules/ajv",
+  "author": {
+    "name": "Vincent Le Goff",
+    "email": "vince.legoff@gmail.com",
+    "url": "https://github.com/zekth"
+  },
+  "bugs": {
+    "url": "https://github.com/fastify/fast-uri/issues"
+  },
+  "bundleDependencies": false,
+  "contributors": [
+    {
+      "name": "Matteo Collina",
+      "email": "hello@matteocollina.com"
+    },
+    {
+      "name": "Gürgün Dayıoğlu",
+      "email": "hey@gurgun.day",
+      "url": "https://heyhey.to/G"
+    },
+    {
+      "name": "Aras Abbasi",
+      "email": "aras.abbasi@gmail.com"
+    },
+    {
+      "name": "Frazer Smith",
+      "email": "frazer.dev@icloud.com",
+      "url": "https://github.com/fdawgs"
+    }
+  ],
+  "deprecated": false,
+  "description": "Dependency-free RFC 3986 URI toolbox",
+  "devDependencies": {
+    "@fastify/pre-commit": "^2.1.0",
+    "ajv": "^8.16.0",
+    "benchmark": "^2.1.4",
+    "coveralls": "^3.1.1",
+    "eslint": "^9.17.0",
+    "neostandard": "^0.12.0",
+    "tape": "^5.8.1",
+    "tsd": "^0.31.0",
+    "uri-js": "^4.4.1"
+  },
+  "funding": [
+    {
+      "type": "github",
+      "url": "https://github.com/sponsors/fastify"
+    },
+    {
+      "type": "opencollective",
+      "url": "https://opencollective.com/fastify"
+    }
+  ],
+  "homepage": "https://github.com/fastify/fast-uri",
+  "license": "BSD-3-Clause",
+  "main": "index.js",
+  "name": "fast-uri",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/fastify/fast-uri.git"
+  },
+  "scripts": {
+    "bench": "node benchmark.js",
+    "lint": "eslint",
+    "lint:fix": "eslint --fix",
+    "test": "npm run test:unit && npm run test:typescript",
+    "test:typescript": "tsd",
+    "test:unit": "tape test/**/*.js",
+    "test:unit:dev": "npm run test:unit -- --coverage-report=html"
+  },
+  "type": "commonjs",
+  "types": "types/index.d.ts",
+  "version": "3.0.5"
+}
Index: imaps-frontend/node_modules/fast-uri/test/ajv.test.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/test/ajv.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/test/ajv.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,39 @@
+const AJV = require('ajv')
+const fastUri = require('../')
+const ajv = new AJV({
+  uriResolver: fastUri // comment this line to see it works with uri-js
+})
+const test = require('tape')
+
+test('ajv', t => {
+  t.plan(1)
+  const schema = {
+    $ref: '#/definitions/Record%3Cstring%2CPerson%3E',
+    definitions: {
+      Person: {
+        type: 'object',
+        properties: {
+          firstName: {
+            type: 'string'
+          }
+        }
+      },
+      'Record<string,Person>': {
+        type: 'object',
+        additionalProperties: {
+          $ref: '#/definitions/Person'
+        }
+      }
+    }
+  }
+
+  const data = {
+    joe: {
+      firstName: 'Joe'
+    }
+
+  }
+
+  const validate = ajv.compile(schema)
+  t.ok(validate(data))
+})
Index: imaps-frontend/node_modules/fast-uri/test/compatibility.test.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/test/compatibility.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/test/compatibility.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,131 @@
+'use strict'
+
+const test = require('tape')
+const fastifyURI = require('../')
+const urijs = require('uri-js')
+
+test('compatibility Parse', (t) => {
+  const toParse = [
+    '//www.g.com/error\n/bleh/bleh',
+    'https://fastify.org',
+    '/definitions/Record%3Cstring%2CPerson%3E',
+    '//10.10.10.10',
+    // '//10.10.000.10', <-- not a valid URI per URI spec: https://datatracker.ietf.org/doc/html/rfc5954#section-4.1
+    '//[2001:db8::7%en0]',
+    '//[2001:dbZ::1]:80',
+    '//[2001:db8::1]:80',
+    '//[2001:db8::001]:80',
+    'uri://user:pass@example.com:123/one/two.three?q1=a1&q2=a2#body',
+    'http://user:pass@example.com:123/one/space in.url?q1=a1&q2=a2#body',
+    'http://User:Pass@example.com:123/one/space in.url?q1=a1&q2=a2#body',
+    'http://A%3AB@example.com:123/one/space',
+    '//[::ffff:129.144.52.38]',
+    'uri://10.10.10.10.example.com/en/process',
+    '//[2606:2800:220:1:248:1893:25c8:1946]/test',
+    'ws://example.com/chat',
+    'ws://example.com/foo?bar=baz',
+    'wss://example.com/?bar=baz',
+    'wss://example.com/chat',
+    'wss://example.com/foo?bar=baz',
+    'wss://example.com/?bar=baz',
+    'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6',
+    'urn:uuid:notauuid-7dec-11d0-a765-00a0c91e6bf6',
+    'urn:example:%D0%B0123,z456',
+    '//[2606:2800:220:1:248:1893:25c8:1946:43209]',
+    'http://foo.bar',
+    'http://',
+    '#/$defs/stringMap',
+    '#/$defs/string%20Map',
+    '#/$defs/string Map',
+    '//?json=%7B%22foo%22%3A%22bar%22%7D'
+    //  'mailto:chris@example.com'-203845,
+    //  'mailto:infobot@example.com?subject=current-issue',
+    //  'mailto:infobot@example.com?body=send%20current-issue',
+    //  'mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index',
+    //  'mailto:list@example.org?In-Reply-To=%3C3469A91.D10AF4C@example.com%3E',
+    //  'mailto:majordomo@example.com?body=subscribe%20bamboo-l',
+    //  'mailto:joe@example.com?cc=bob@example.com&body=hello',
+    //  'mailto:gorby%25kremvax@example.com',
+    //  'mailto:unlikely%3Faddress@example.com?blat=foop',
+    //  'mailto:Mike%26family@example.org',
+    //  'mailto:%22not%40me%22@example.org',
+    //  'mailto:%22oh%5C%5Cno%22@example.org',
+    //  'mailto:%22%5C%5C%5C%22it\'s%5C%20ugly%5C%5C%5C%22%22@example.org',
+    //  'mailto:user@example.org?subject=caf%C3%A9',
+    //  'mailto:user@example.org?subject=%3D%3Futf-8%3FQ%3Fcaf%3DC3%3DA9%3F%3D',
+    //  'mailto:user@example.org?subject=%3D%3Fiso-8859-1%3FQ%3Fcaf%3DE9%3F%3D',
+    //  'mailto:user@example.org?subject=caf%C3%A9&body=caf%C3%A9',
+    //  'mailto:user@%E7%B4%8D%E8%B1%86.example.org?subject=Test&body=NATTO'
+  ]
+  toParse.forEach((x) => {
+    t.same(fastifyURI.parse(x), urijs.parse(x), 'Compatibility parse: ' + x)
+  })
+  t.end()
+})
+
+test('compatibility serialize', (t) => {
+  const toSerialize = [
+    { host: '10.10.10.10.example.com' },
+    { host: '2001:db8::7' },
+    { host: '::ffff:129.144.52.38' },
+    { host: '2606:2800:220:1:248:1893:25c8:1946' },
+    { host: '10.10.10.10.example.com' },
+    { host: '10.10.10.10' },
+    { path: '?query' },
+    { path: 'foo:bar' },
+    { path: '//path' },
+    {
+      scheme: 'uri',
+      host: 'example.com',
+      port: '9000'
+    },
+    {
+      scheme: 'uri',
+      userinfo: 'foo:bar',
+      host: 'example.com',
+      port: 1,
+      path: 'path',
+      query: 'query',
+      fragment: 'fragment'
+    },
+    {
+      scheme: '',
+      userinfo: '',
+      host: '',
+      port: 0,
+      path: '',
+      query: '',
+      fragment: ''
+    },
+    {
+      scheme: undefined,
+      userinfo: undefined,
+      host: undefined,
+      port: undefined,
+      path: undefined,
+      query: undefined,
+      fragment: undefined
+    },
+    { host: 'fe80::a%en1' },
+    { host: 'fe80::a%25en1' },
+    {
+      scheme: 'ws',
+      host: 'example.com',
+      resourceName: '/foo?bar',
+      secure: true
+    },
+    {
+      scheme: 'scheme',
+      path: 'with:colon'
+    }
+  ]
+  toSerialize.forEach((x) => {
+    const r = JSON.stringify(x)
+    t.same(
+      fastifyURI.serialize(x),
+      urijs.serialize(x),
+      'Compatibility serialize: ' + JSON.stringify(r)
+    )
+  })
+  t.end()
+})
Index: imaps-frontend/node_modules/fast-uri/test/equal.test.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/test/equal.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/test/equal.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,103 @@
+'use strict'
+
+const test = require('tape')
+const URI = require('../')
+
+const fn = URI.equal
+const runTest = (t, suite) => {
+  suite.forEach(s => {
+    const operator = s.result ? '==' : '!='
+    t.equal(fn(s.pair[0], s.pair[1]), s.result, `${s.pair[0]} ${operator} ${s.pair[1]}`)
+    t.equal(fn(s.pair[1], s.pair[0]), s.result, `${s.pair[1]} ${operator} ${s.pair[0]}`)
+  })
+}
+
+test('URI Equals', (t) => {
+  const suite = [
+    { pair: ['example://a/b/c/%7Bfoo%7D', 'eXAMPLE://a/./b/../b/%63/%7bfoo%7d'], result: true }, // test from RFC 3986
+    { pair: ['http://example.org/~user', 'http://example.org/%7euser'], result: true } // test from RFC 3987
+  ]
+  runTest(t, suite)
+  t.end()
+})
+
+//   test('IRI Equals', (t) => {
+//     // example from RFC 3987
+//     t.equal(URI.equal('example://a/b/c/%7Bfoo%7D/ros\xE9', 'eXAMPLE://a/./b/../b/%63/%7bfoo%7d/ros%C3%A9', IRI_OPTION), true)
+//     t.end()
+//   })
+
+test('HTTP Equals', (t) => {
+  const suite = [
+    // test from RFC 2616
+    { pair: ['http://abc.com:80/~smith/home.html', 'http://abc.com/~smith/home.html'], result: true },
+    { pair: [{ scheme: 'http', host: 'abc.com', port: 80, path: '/~smith/home.html' }, 'http://abc.com/~smith/home.html'], result: true },
+    { pair: ['http://ABC.com/%7Esmith/home.html', 'http://abc.com/~smith/home.html'], result: true },
+    { pair: ['http://ABC.com:/%7esmith/home.html', 'http://abc.com/~smith/home.html'], result: true },
+    { pair: ['HTTP://ABC.COM', 'http://abc.com/'], result: true },
+    // test from RFC 3986
+    { pair: ['http://example.com:/', 'http://example.com:80/'], result: true }
+  ]
+  runTest(t, suite)
+  t.end()
+})
+
+test('HTTPS Equals', (t) => {
+  const suite = [
+    { pair: ['https://example.com', 'https://example.com:443/'], result: true },
+    { pair: ['https://example.com:/', 'https://example.com:443/'], result: true }
+  ]
+  runTest(t, suite)
+  t.end()
+})
+
+test('URN Equals', (t) => {
+  const suite = [
+    // test from RFC 2141
+    { pair: ['urn:foo:a123,456', 'urn:foo:a123,456'], result: true },
+    { pair: ['urn:foo:a123,456', 'URN:foo:a123,456'], result: true },
+    { pair: ['urn:foo:a123,456', 'urn:FOO:a123,456'], result: true }
+  ]
+
+  // Disabling for now as the whole equal logic might need
+  // to be refactored
+  // t.equal(URI.equal('urn:foo:a123,456', 'urn:foo:A123,456'), false)
+  // t.equal(URI.equal('urn:foo:a123%2C456', 'URN:FOO:a123%2c456'), true)
+
+  runTest(t, suite)
+  t.end()
+})
+
+test('UUID Equals', (t) => {
+  const suite = [
+    { pair: ['URN:UUID:F81D4FAE-7DEC-11D0-A765-00A0C91E6BF6', 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6'], result: true }
+  ]
+
+  runTest(t, suite)
+  t.end()
+})
+
+// test('Mailto Equals', (t) => {
+//   // tests from RFC 6068
+//   t.equal(URI.equal('mailto:addr1@an.example,addr2@an.example', 'mailto:?to=addr1@an.example,addr2@an.example'), true)
+//   t.equal(URI.equal('mailto:?to=addr1@an.example,addr2@an.example', 'mailto:addr1@an.example?to=addr2@an.example'), true)
+//   t.end()
+// })
+
+test('WS Equal', (t) => {
+  const suite = [
+    { pair: ['WS://ABC.COM:80/chat#one', 'ws://abc.com/chat'], result: true }
+  ]
+
+  runTest(t, suite)
+  t.end()
+})
+
+test('WSS Equal', (t) => {
+  const suite = [
+    { pair: ['WSS://ABC.COM:443/chat#one', 'wss://abc.com/chat'], result: true }
+  ]
+
+  runTest(t, suite)
+  t.end()
+})
Index: imaps-frontend/node_modules/fast-uri/test/parse.test.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/test/parse.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/test/parse.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,318 @@
+'use strict'
+
+const test = require('tape')
+const URI = require('../')
+
+test('URI parse', (t) => {
+  let components
+
+  // scheme
+  components = URI.parse('uri:')
+  t.equal(components.error, undefined, 'scheme errors')
+  t.equal(components.scheme, 'uri', 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // userinfo
+  components = URI.parse('//@')
+  t.equal(components.error, undefined, 'userinfo errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, "@", "authority");
+  t.equal(components.userinfo, '', 'userinfo')
+  t.equal(components.host, '', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // host
+  components = URI.parse('//')
+  t.equal(components.error, undefined, 'host errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, "", "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // port
+  components = URI.parse('//:')
+  t.equal(components.error, undefined, 'port errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, ":", "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '', 'host')
+  t.equal(components.port, '', 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // path
+  components = URI.parse('')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // query
+  components = URI.parse('?')
+  t.equal(components.error, undefined, 'query errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, '', 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // fragment
+  components = URI.parse('#')
+  t.equal(components.error, undefined, 'fragment errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '', 'fragment')
+
+  // fragment with character tabulation
+  components = URI.parse('#\t')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%09', 'fragment')
+
+  // fragment with line feed
+  components = URI.parse('#\n')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%0A', 'fragment')
+
+  // fragment with line tabulation
+  components = URI.parse('#\v')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%0B', 'fragment')
+
+  // fragment with form feed
+  components = URI.parse('#\f')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%0C', 'fragment')
+
+  // fragment with carriage return
+  components = URI.parse('#\r')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%0D', 'fragment')
+
+  // all
+  components = URI.parse('uri://user:pass@example.com:123/one/two.three?q1=a1&q2=a2#body')
+  t.equal(components.error, undefined, 'all errors')
+  t.equal(components.scheme, 'uri', 'scheme')
+  // t.equal(components.authority, "user:pass@example.com:123", "authority");
+  t.equal(components.userinfo, 'user:pass', 'userinfo')
+  t.equal(components.host, 'example.com', 'host')
+  t.equal(components.port, 123, 'port')
+  t.equal(components.path, '/one/two.three', 'path')
+  t.equal(components.query, 'q1=a1&q2=a2', 'query')
+  t.equal(components.fragment, 'body', 'fragment')
+
+  // IPv4address
+  components = URI.parse('//10.10.10.10')
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '10.10.10.10', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv4address with unformated 0 stay as-is
+  components = URI.parse('//10.10.000.10') // not valid as per https://datatracker.ietf.org/doc/html/rfc5954#section-4.1
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '10.10.000.10', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+  components = URI.parse('//01.01.01.01') // not valid in URIs: https://datatracker.ietf.org/doc/html/rfc3986#section-7.4
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '01.01.01.01', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address
+  components = URI.parse('//[2001:db8::7]')
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '2001:db8::7', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // invalid IPv6
+  components = URI.parse('//[2001:dbZ::7]')
+  t.equal(components.host, '[2001:dbz::7]')
+
+  // mixed IPv4address & IPv6address
+  components = URI.parse('//[::ffff:129.144.52.38]')
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '::ffff:129.144.52.38', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // mixed IPv4address & reg-name, example from terion-name (https://github.com/garycourt/uri-js/issues/4)
+  components = URI.parse('uri://10.10.10.10.example.com/en/process')
+  t.equal(components.error, undefined, 'mixed errors')
+  t.equal(components.scheme, 'uri', 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '10.10.10.10.example.com', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '/en/process', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address, example from bkw (https://github.com/garycourt/uri-js/pull/16)
+  components = URI.parse('//[2606:2800:220:1:248:1893:25c8:1946]/test')
+  t.equal(components.error, undefined, 'IPv6address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '2606:2800:220:1:248:1893:25c8:1946', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '/test', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address, example from RFC 5952
+  components = URI.parse('//[2001:db8::1]:80')
+  t.equal(components.error, undefined, 'IPv6address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '2001:db8::1', 'host')
+  t.equal(components.port, 80, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address with zone identifier, RFC 6874
+  components = URI.parse('//[fe80::a%25en1]')
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, 'fe80::a%en1', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address with an unescaped interface specifier, example from pekkanikander (https://github.com/garycourt/uri-js/pull/22)
+  components = URI.parse('//[2001:db8::7%en0]')
+  t.equal(components.error, undefined, 'IPv6address interface errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '2001:db8::7%en0', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // UUID V1
+  components = URI.parse('urn:uuid:b571b0bc-4713-11ec-81d3-0242ac130003')
+  t.equal(components.error, undefined, 'errors')
+  t.equal(components.scheme, 'urn', 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, undefined, 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+  t.equal(components.nid, 'uuid', 'nid')
+  t.equal(components.nss, undefined, 'nss')
+  t.equal(components.uuid, 'b571b0bc-4713-11ec-81d3-0242ac130003', 'uuid')
+
+  // UUID v4
+  components = URI.parse('urn:uuid:97a32222-89b7-420e-8507-4360723e2c2a')
+  t.equal(components.uuid, '97a32222-89b7-420e-8507-4360723e2c2a', 'uuid')
+
+  components = URI.parse('urn:uuid:notauuid-7dec-11d0-a765-00a0c91e6bf6')
+  t.notSame(components.error, undefined, 'errors')
+
+  components = URI.parse('urn:foo:a123,456')
+  t.equal(components.error, undefined, 'errors')
+  t.equal(components.scheme, 'urn', 'scheme')
+  // t.equal(components.authority, undefined, "authority");
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, undefined, 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+  t.equal(components.nid, 'foo', 'nid')
+  t.equal(components.nss, 'a123,456', 'nss')
+
+  components = URI.parse('//[2606:2800:220:1:248:1893:25c8:1946:43209]')
+  t.equal(components.host, '[2606:2800:220:1:248:1893:25c8:1946:43209]')
+
+  components = URI.parse('urn:foo:|\\24fpl')
+  t.equal(components.error, 'URN can not be parsed.')
+  t.end()
+})
Index: imaps-frontend/node_modules/fast-uri/test/resolve.test.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/test/resolve.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/test/resolve.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,75 @@
+'use strict'
+
+const test = require('tape')
+const URI = require('../')
+
+test('URI Resolving', (t) => {
+  // normal examples from RFC 3986
+  const base = 'uri://a/b/c/d;p?q'
+  t.equal(URI.resolve(base, 'g:h'), 'g:h', 'g:h')
+  t.equal(URI.resolve(base, 'g:h'), 'g:h', 'g:h')
+  t.equal(URI.resolve(base, 'g'), 'uri://a/b/c/g', 'g')
+  t.equal(URI.resolve(base, './g'), 'uri://a/b/c/g', './g')
+  t.equal(URI.resolve(base, 'g/'), 'uri://a/b/c/g/', 'g/')
+  t.equal(URI.resolve(base, '/g'), 'uri://a/g', '/g')
+  t.equal(URI.resolve(base, '//g'), 'uri://g', '//g')
+  t.equal(URI.resolve(base, '?y'), 'uri://a/b/c/d;p?y', '?y')
+  t.equal(URI.resolve(base, 'g?y'), 'uri://a/b/c/g?y', 'g?y')
+  t.equal(URI.resolve(base, '#s'), 'uri://a/b/c/d;p?q#s', '#s')
+  t.equal(URI.resolve(base, 'g#s'), 'uri://a/b/c/g#s', 'g#s')
+  t.equal(URI.resolve(base, 'g?y#s'), 'uri://a/b/c/g?y#s', 'g?y#s')
+  t.equal(URI.resolve(base, ';x'), 'uri://a/b/c/;x', ';x')
+  t.equal(URI.resolve(base, 'g;x'), 'uri://a/b/c/g;x', 'g;x')
+  t.equal(URI.resolve(base, 'g;x?y#s'), 'uri://a/b/c/g;x?y#s', 'g;x?y#s')
+  t.equal(URI.resolve(base, ''), 'uri://a/b/c/d;p?q', '')
+  t.equal(URI.resolve(base, '.'), 'uri://a/b/c/', '.')
+  t.equal(URI.resolve(base, './'), 'uri://a/b/c/', './')
+  t.equal(URI.resolve(base, '..'), 'uri://a/b/', '..')
+  t.equal(URI.resolve(base, '../'), 'uri://a/b/', '../')
+  t.equal(URI.resolve(base, '../g'), 'uri://a/b/g', '../g')
+  t.equal(URI.resolve(base, '../..'), 'uri://a/', '../..')
+  t.equal(URI.resolve(base, '../../'), 'uri://a/', '../../')
+  t.equal(URI.resolve(base, '../../g'), 'uri://a/g', '../../g')
+
+  // abnormal examples from RFC 3986
+  t.equal(URI.resolve(base, '../../../g'), 'uri://a/g', '../../../g')
+  t.equal(URI.resolve(base, '../../../../g'), 'uri://a/g', '../../../../g')
+
+  t.equal(URI.resolve(base, '/./g'), 'uri://a/g', '/./g')
+  t.equal(URI.resolve(base, '/../g'), 'uri://a/g', '/../g')
+  t.equal(URI.resolve(base, 'g.'), 'uri://a/b/c/g.', 'g.')
+  t.equal(URI.resolve(base, '.g'), 'uri://a/b/c/.g', '.g')
+  t.equal(URI.resolve(base, 'g..'), 'uri://a/b/c/g..', 'g..')
+  t.equal(URI.resolve(base, '..g'), 'uri://a/b/c/..g', '..g')
+
+  t.equal(URI.resolve(base, './../g'), 'uri://a/b/g', './../g')
+  t.equal(URI.resolve(base, './g/.'), 'uri://a/b/c/g/', './g/.')
+  t.equal(URI.resolve(base, 'g/./h'), 'uri://a/b/c/g/h', 'g/./h')
+  t.equal(URI.resolve(base, 'g/../h'), 'uri://a/b/c/h', 'g/../h')
+  t.equal(URI.resolve(base, 'g;x=1/./y'), 'uri://a/b/c/g;x=1/y', 'g;x=1/./y')
+  t.equal(URI.resolve(base, 'g;x=1/../y'), 'uri://a/b/c/y', 'g;x=1/../y')
+
+  t.equal(URI.resolve(base, 'g?y/./x'), 'uri://a/b/c/g?y/./x', 'g?y/./x')
+  t.equal(URI.resolve(base, 'g?y/../x'), 'uri://a/b/c/g?y/../x', 'g?y/../x')
+  t.equal(URI.resolve(base, 'g#s/./x'), 'uri://a/b/c/g#s/./x', 'g#s/./x')
+  t.equal(URI.resolve(base, 'g#s/../x'), 'uri://a/b/c/g#s/../x', 'g#s/../x')
+
+  t.equal(URI.resolve(base, 'uri:g'), 'uri:g', 'uri:g')
+  t.equal(URI.resolve(base, 'uri:g', { tolerant: true }), 'uri://a/b/c/g', 'uri:g')
+
+  // examples by PAEz
+  // example was provided to avoid infinite loop within regex
+  // this is not the case anymore
+  // t.equal(URI.resolve('//www.g.com/', '/adf\ngf'), '//www.g.com/adf%0Agf', '/adf\\ngf')
+  // t.equal(URI.resolve('//www.g.com/error\n/bleh/bleh', '..'), '//www.g.com/error%0A/', '//www.g.com/error\\n/bleh/bleh')
+  t.end()
+})
+
+test('URN Resolving', (t) => {
+  // example from epoberezkin
+  t.equal(URI.resolve('', 'urn:some:ip:prop'), 'urn:some:ip:prop', 'urn:some:ip:prop')
+  t.equal(URI.resolve('#', 'urn:some:ip:prop'), 'urn:some:ip:prop', 'urn:some:ip:prop')
+  t.equal(URI.resolve('urn:some:ip:prop', 'urn:some:ip:prop'), 'urn:some:ip:prop', 'urn:some:ip:prop')
+  t.equal(URI.resolve('urn:some:other:prop', 'urn:some:ip:prop'), 'urn:some:ip:prop', 'urn:some:ip:prop')
+  t.end()
+})
Index: imaps-frontend/node_modules/fast-uri/test/serialize.test.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/test/serialize.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/test/serialize.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,143 @@
+'use strict'
+
+const test = require('tape')
+const URI = require('../')
+
+test('URI Serialize', (t) => {
+  let components = {
+    scheme: undefined,
+    userinfo: undefined,
+    host: undefined,
+    port: undefined,
+    path: undefined,
+    query: undefined,
+    fragment: undefined
+  }
+  t.equal(URI.serialize(components), '', 'Undefined Components')
+
+  components = {
+    scheme: '',
+    userinfo: '',
+    host: '',
+    port: 0,
+    path: '',
+    query: '',
+    fragment: ''
+  }
+  t.equal(URI.serialize(components), '//@:0?#', 'Empty Components')
+
+  components = {
+    scheme: 'uri',
+    userinfo: 'foo:bar',
+    host: 'example.com',
+    port: 1,
+    path: 'path',
+    query: 'query',
+    fragment: 'fragment'
+  }
+  t.equal(URI.serialize(components), 'uri://foo:bar@example.com:1/path?query#fragment', 'All Components')
+
+  components = {
+    scheme: 'uri',
+    host: 'example.com',
+    port: '9000'
+  }
+  t.equal(URI.serialize(components), 'uri://example.com:9000', 'String port')
+
+  t.equal(URI.serialize({ path: '//path' }), '/%2Fpath', 'Double slash path')
+  t.equal(URI.serialize({ path: 'foo:bar' }), 'foo%3Abar', 'Colon path')
+  t.equal(URI.serialize({ path: '?query' }), '%3Fquery', 'Query path')
+
+  t.equal(URI.serialize({ host: '10.10.10.10' }), '//10.10.10.10', 'IPv4address')
+
+  // mixed IPv4address & reg-name, example from terion-name (https://github.com/garycourt/uri-js/issues/4)
+  t.equal(URI.serialize({ host: '10.10.10.10.example.com' }), '//10.10.10.10.example.com', 'Mixed IPv4address & reg-name')
+
+  // IPv6address
+  t.equal(URI.serialize({ host: '2001:db8::7' }), '//[2001:db8::7]', 'IPv6 Host')
+  t.equal(URI.serialize({ host: '::ffff:129.144.52.38' }), '//[::ffff:129.144.52.38]', 'IPv6 Mixed Host')
+  t.equal(URI.serialize({ host: '2606:2800:220:1:248:1893:25c8:1946' }), '//[2606:2800:220:1:248:1893:25c8:1946]', 'IPv6 Full Host')
+
+  // IPv6address with zone identifier, RFC 6874
+  t.equal(URI.serialize({ host: 'fe80::a%en1' }), '//[fe80::a%25en1]', 'IPv6 Zone Unescaped Host')
+  t.equal(URI.serialize({ host: 'fe80::a%25en1' }), '//[fe80::a%25en1]', 'IPv6 Zone Escaped Host')
+
+  t.end()
+})
+
+test('WS serialize', (t) => {
+  t.equal(URI.serialize({ scheme: 'ws' }), 'ws:')
+  t.equal(URI.serialize({ scheme: 'ws', host: 'example.com' }), 'ws://example.com')
+  t.equal(URI.serialize({ scheme: 'ws', resourceName: '/' }), 'ws:')
+  t.equal(URI.serialize({ scheme: 'ws', resourceName: '/foo' }), 'ws:/foo')
+  t.equal(URI.serialize({ scheme: 'ws', resourceName: '/foo?bar' }), 'ws:/foo?bar')
+  t.equal(URI.serialize({ scheme: 'ws', secure: false }), 'ws:')
+  t.equal(URI.serialize({ scheme: 'ws', secure: true }), 'wss:')
+  t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo' }), 'ws://example.com/foo')
+  t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar' }), 'ws://example.com/foo?bar')
+  t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', secure: false }), 'ws://example.com')
+  t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', secure: true }), 'wss://example.com')
+  t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: false }), 'ws://example.com/foo?bar')
+  t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: true }), 'wss://example.com/foo?bar')
+  t.end()
+})
+
+test('WSS serialize', (t) => {
+  t.equal(URI.serialize({ scheme: 'wss' }), 'wss:')
+  t.equal(URI.serialize({ scheme: 'wss', host: 'example.com' }), 'wss://example.com')
+  t.equal(URI.serialize({ scheme: 'wss', resourceName: '/' }), 'wss:')
+  t.equal(URI.serialize({ scheme: 'wss', resourceName: '/foo' }), 'wss:/foo')
+  t.equal(URI.serialize({ scheme: 'wss', resourceName: '/foo?bar' }), 'wss:/foo?bar')
+  t.equal(URI.serialize({ scheme: 'wss', secure: false }), 'ws:')
+  t.equal(URI.serialize({ scheme: 'wss', secure: true }), 'wss:')
+  t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo' }), 'wss://example.com/foo')
+  t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo?bar' }), 'wss://example.com/foo?bar')
+  t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', secure: false }), 'ws://example.com')
+  t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', secure: true }), 'wss://example.com')
+  t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo?bar', secure: false }), 'ws://example.com/foo?bar')
+  t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo?bar', secure: true }), 'wss://example.com/foo?bar')
+
+  t.end()
+})
+
+test('URN serialize', (t) => {
+// example from RFC 2141
+  const components = {
+    scheme: 'urn',
+    nid: 'foo',
+    nss: 'a123,456'
+  }
+  t.equal(URI.serialize(components), 'urn:foo:a123,456')
+  // example from RFC 4122
+  let uuidcomponents = {
+    scheme: 'urn',
+    nid: 'uuid',
+    uuid: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6'
+  }
+  t.equal(URI.serialize(uuidcomponents), 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6')
+
+  uuidcomponents = {
+    scheme: 'urn',
+    nid: 'uuid',
+    uuid: 'notauuid-7dec-11d0-a765-00a0c91e6bf6'
+  }
+  t.equal(URI.serialize(uuidcomponents), 'urn:uuid:notauuid-7dec-11d0-a765-00a0c91e6bf6')
+  t.end()
+})
+test('URN NID Override', (t) => {
+  let components = URI.parse('urn:foo:f81d4fae-7dec-11d0-a765-00a0c91e6bf6', { nid: 'uuid' })
+  t.equal(components.error, undefined, 'errors')
+  t.equal(components.scheme, 'urn', 'scheme')
+  t.equal(components.path, undefined, 'path')
+  t.equal(components.nid, 'foo', 'nid')
+  t.equal(components.nss, undefined, 'nss')
+  t.equal(components.uuid, 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6', 'uuid')
+
+  components = {
+    scheme: 'urn',
+    nid: 'foo',
+    uuid: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6'
+  }
+  t.equal(URI.serialize(components, { nid: 'uuid' }), 'urn:foo:f81d4fae-7dec-11d0-a765-00a0c91e6bf6')
+  t.end()
+})
Index: imaps-frontend/node_modules/fast-uri/test/uri-js.test.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/test/uri-js.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/test/uri-js.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,912 @@
+'use strict'
+
+const test = require('tape')
+const URI = require('../index')
+
+/**
+ * URI.js
+ *
+ * @fileoverview An RFC 3986 compliant, scheme extendable URI parsing/normalizing/resolving/serializing library for JavaScript.
+ * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
+ * @see http://github.com/garycourt/uri-js
+ */
+
+/**
+ * Copyright 2011 Gary Court. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of Gary Court.
+ */
+
+test('Acquire URI', (t) => {
+  t.ok(URI)
+  t.end()
+})
+
+test('URI Parsing', (t) => {
+  let components
+
+  // scheme
+  components = URI.parse('uri:')
+  t.equal(components.error, undefined, 'scheme errors')
+  t.equal(components.scheme, 'uri', 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // userinfo
+  components = URI.parse('//@')
+  t.equal(components.error, undefined, 'userinfo errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, '', 'userinfo')
+  t.equal(components.host, '', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // host
+  components = URI.parse('//')
+  t.equal(components.error, undefined, 'host errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // port
+  components = URI.parse('//:')
+  t.equal(components.error, undefined, 'port errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '', 'host')
+  t.equal(components.port, '', 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // path
+  components = URI.parse('')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // query
+  components = URI.parse('?')
+  t.equal(components.error, undefined, 'query errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, '', 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // fragment
+  components = URI.parse('#')
+  t.equal(components.error, undefined, 'fragment errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '', 'fragment')
+
+  // fragment with character tabulation
+  components = URI.parse('#\t')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%09', 'fragment')
+
+  // fragment with line feed
+  components = URI.parse('#\n')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%0A', 'fragment')
+
+  // fragment with line tabulation
+  components = URI.parse('#\v')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%0B', 'fragment')
+
+  // fragment with form feed
+  components = URI.parse('#\f')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%0C', 'fragment')
+
+  // fragment with carriage return
+  components = URI.parse('#\r')
+  t.equal(components.error, undefined, 'path errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, undefined, 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, '%0D', 'fragment')
+
+  // all
+  components = URI.parse('uri://user:pass@example.com:123/one/two.three?q1=a1&q2=a2#body')
+  t.equal(components.error, undefined, 'all errors')
+  t.equal(components.scheme, 'uri', 'scheme')
+  t.equal(components.userinfo, 'user:pass', 'userinfo')
+  t.equal(components.host, 'example.com', 'host')
+  t.equal(components.port, 123, 'port')
+  t.equal(components.path, '/one/two.three', 'path')
+  t.equal(components.query, 'q1=a1&q2=a2', 'query')
+  t.equal(components.fragment, 'body', 'fragment')
+
+  // IPv4address
+  components = URI.parse('//10.10.10.10')
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '10.10.10.10', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address
+  components = URI.parse('//[2001:db8::7]')
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '2001:db8::7', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // mixed IPv4address & IPv6address
+  components = URI.parse('//[::ffff:129.144.52.38]')
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '::ffff:129.144.52.38', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // mixed IPv4address & reg-name, example from terion-name (https://github.com/garycourt/uri-js/issues/4)
+  components = URI.parse('uri://10.10.10.10.example.com/en/process')
+  t.equal(components.error, undefined, 'mixed errors')
+  t.equal(components.scheme, 'uri', 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '10.10.10.10.example.com', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '/en/process', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address, example from bkw (https://github.com/garycourt/uri-js/pull/16)
+  components = URI.parse('//[2606:2800:220:1:248:1893:25c8:1946]/test')
+  t.equal(components.error, undefined, 'IPv6address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '2606:2800:220:1:248:1893:25c8:1946', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '/test', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address, example from RFC 5952
+  components = URI.parse('//[2001:db8::1]:80')
+  t.equal(components.error, undefined, 'IPv6address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '2001:db8::1', 'host')
+  t.equal(components.port, 80, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address with zone identifier, RFC 6874
+  components = URI.parse('//[fe80::a%25en1]')
+  t.equal(components.error, undefined, 'IPv4address errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, 'fe80::a%en1', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  // IPv6address with an unescaped interface specifier, example from pekkanikander (https://github.com/garycourt/uri-js/pull/22)
+  components = URI.parse('//[2001:db8::7%en0]')
+  t.equal(components.error, undefined, 'IPv6address interface errors')
+  t.equal(components.scheme, undefined, 'scheme')
+  t.equal(components.userinfo, undefined, 'userinfo')
+  t.equal(components.host, '2001:db8::7%en0', 'host')
+  t.equal(components.port, undefined, 'port')
+  t.equal(components.path, '', 'path')
+  t.equal(components.query, undefined, 'query')
+  t.equal(components.fragment, undefined, 'fragment')
+
+  t.end()
+})
+
+test('URI Serialization', (t) => {
+  let components = {
+    scheme: undefined,
+    userinfo: undefined,
+    host: undefined,
+    port: undefined,
+    path: undefined,
+    query: undefined,
+    fragment: undefined
+  }
+  t.equal(URI.serialize(components), '', 'Undefined Components')
+
+  components = {
+    scheme: '',
+    userinfo: '',
+    host: '',
+    port: 0,
+    path: '',
+    query: '',
+    fragment: ''
+  }
+  t.equal(URI.serialize(components), '//@:0?#', 'Empty Components')
+
+  components = {
+    scheme: 'uri',
+    userinfo: 'foo:bar',
+    host: 'example.com',
+    port: 1,
+    path: 'path',
+    query: 'query',
+    fragment: 'fragment'
+  }
+  t.equal(URI.serialize(components), 'uri://foo:bar@example.com:1/path?query#fragment', 'All Components')
+
+  components = {
+    scheme: 'uri',
+    host: 'example.com',
+    port: '9000'
+  }
+  t.equal(URI.serialize(components), 'uri://example.com:9000', 'String port')
+
+  t.equal(URI.serialize({ path: '//path' }), '/%2Fpath', 'Double slash path')
+  t.equal(URI.serialize({ path: 'foo:bar' }), 'foo%3Abar', 'Colon path')
+  t.equal(URI.serialize({ path: '?query' }), '%3Fquery', 'Query path')
+
+  // mixed IPv4address & reg-name, example from terion-name (https://github.com/garycourt/uri-js/issues/4)
+  t.equal(URI.serialize({ host: '10.10.10.10.example.com' }), '//10.10.10.10.example.com', 'Mixed IPv4address & reg-name')
+
+  // IPv6address
+  t.equal(URI.serialize({ host: '2001:db8::7' }), '//[2001:db8::7]', 'IPv6 Host')
+  t.equal(URI.serialize({ host: '::ffff:129.144.52.38' }), '//[::ffff:129.144.52.38]', 'IPv6 Mixed Host')
+  t.equal(URI.serialize({ host: '2606:2800:220:1:248:1893:25c8:1946' }), '//[2606:2800:220:1:248:1893:25c8:1946]', 'IPv6 Full Host')
+
+  // IPv6address with zone identifier, RFC 6874
+  t.equal(URI.serialize({ host: 'fe80::a%en1' }), '//[fe80::a%25en1]', 'IPv6 Zone Unescaped Host')
+  t.equal(URI.serialize({ host: 'fe80::a%25en1' }), '//[fe80::a%25en1]', 'IPv6 Zone Escaped Host')
+
+  t.end()
+})
+
+test('URI Resolving', { skip: true }, (t) => {
+  // normal examples from RFC 3986
+  const base = 'uri://a/b/c/d;p?q'
+  t.equal(URI.resolve(base, 'g:h'), 'g:h', 'g:h')
+  t.equal(URI.resolve(base, 'g'), 'uri://a/b/c/g', 'g')
+  t.equal(URI.resolve(base, './g'), 'uri://a/b/c/g', './g')
+  t.equal(URI.resolve(base, 'g/'), 'uri://a/b/c/g/', 'g/')
+  t.equal(URI.resolve(base, '/g'), 'uri://a/g', '/g')
+  t.equal(URI.resolve(base, '//g'), 'uri://g', '//g')
+  t.equal(URI.resolve(base, '?y'), 'uri://a/b/c/d;p?y', '?y')
+  t.equal(URI.resolve(base, 'g?y'), 'uri://a/b/c/g?y', 'g?y')
+  t.equal(URI.resolve(base, '#s'), 'uri://a/b/c/d;p?q#s', '#s')
+  t.equal(URI.resolve(base, 'g#s'), 'uri://a/b/c/g#s', 'g#s')
+  t.equal(URI.resolve(base, 'g?y#s'), 'uri://a/b/c/g?y#s', 'g?y#s')
+  t.equal(URI.resolve(base, ';x'), 'uri://a/b/c/;x', ';x')
+  t.equal(URI.resolve(base, 'g;x'), 'uri://a/b/c/g;x', 'g;x')
+  t.equal(URI.resolve(base, 'g;x?y#s'), 'uri://a/b/c/g;x?y#s', 'g;x?y#s')
+  t.equal(URI.resolve(base, ''), 'uri://a/b/c/d;p?q', '')
+  t.equal(URI.resolve(base, '.'), 'uri://a/b/c/', '.')
+  t.equal(URI.resolve(base, './'), 'uri://a/b/c/', './')
+  t.equal(URI.resolve(base, '..'), 'uri://a/b/', '..')
+  t.equal(URI.resolve(base, '../'), 'uri://a/b/', '../')
+  t.equal(URI.resolve(base, '../g'), 'uri://a/b/g', '../g')
+  t.equal(URI.resolve(base, '../..'), 'uri://a/', '../..')
+  t.equal(URI.resolve(base, '../../'), 'uri://a/', '../../')
+  t.equal(URI.resolve(base, '../../g'), 'uri://a/g', '../../g')
+
+  // abnormal examples from RFC 3986
+  t.equal(URI.resolve(base, '../../../g'), 'uri://a/g', '../../../g')
+  t.equal(URI.resolve(base, '../../../../g'), 'uri://a/g', '../../../../g')
+
+  t.equal(URI.resolve(base, '/./g'), 'uri://a/g', '/./g')
+  t.equal(URI.resolve(base, '/../g'), 'uri://a/g', '/../g')
+  t.equal(URI.resolve(base, 'g.'), 'uri://a/b/c/g.', 'g.')
+  t.equal(URI.resolve(base, '.g'), 'uri://a/b/c/.g', '.g')
+  t.equal(URI.resolve(base, 'g..'), 'uri://a/b/c/g..', 'g..')
+  t.equal(URI.resolve(base, '..g'), 'uri://a/b/c/..g', '..g')
+
+  t.equal(URI.resolve(base, './../g'), 'uri://a/b/g', './../g')
+  t.equal(URI.resolve(base, './g/.'), 'uri://a/b/c/g/', './g/.')
+  t.equal(URI.resolve(base, 'g/./h'), 'uri://a/b/c/g/h', 'g/./h')
+  t.equal(URI.resolve(base, 'g/../h'), 'uri://a/b/c/h', 'g/../h')
+  t.equal(URI.resolve(base, 'g;x=1/./y'), 'uri://a/b/c/g;x=1/y', 'g;x=1/./y')
+  t.equal(URI.resolve(base, 'g;x=1/../y'), 'uri://a/b/c/y', 'g;x=1/../y')
+
+  t.equal(URI.resolve(base, 'g?y/./x'), 'uri://a/b/c/g?y/./x', 'g?y/./x')
+  t.equal(URI.resolve(base, 'g?y/../x'), 'uri://a/b/c/g?y/../x', 'g?y/../x')
+  t.equal(URI.resolve(base, 'g#s/./x'), 'uri://a/b/c/g#s/./x', 'g#s/./x')
+  t.equal(URI.resolve(base, 'g#s/../x'), 'uri://a/b/c/g#s/../x', 'g#s/../x')
+
+  t.equal(URI.resolve(base, 'uri:g'), 'uri:g', 'uri:g')
+  t.equal(URI.resolve(base, 'uri:g', { tolerant: true }), 'uri://a/b/c/g', 'uri:g')
+
+  // examples by PAEz
+  t.equal(URI.resolve('//www.g.com/', '/adf\ngf'), '//www.g.com/adf%0Agf', '/adf\\ngf')
+  t.equal(URI.resolve('//www.g.com/error\n/bleh/bleh', '..'), '//www.g.com/error%0A/', '//www.g.com/error\\n/bleh/bleh')
+
+  t.end()
+})
+
+test('URI Normalizing', { skip: true }, (t) => {
+  // test from RFC 3987
+  t.equal(URI.normalize('uri://www.example.org/red%09ros\xE9#red'), 'uri://www.example.org/red%09ros%C3%A9#red')
+
+  // IPv4address
+  t.equal(URI.normalize('//192.068.001.000'), '//192.68.1.0')
+
+  // IPv6address, example from RFC 3513
+  t.equal(URI.normalize('http://[1080::8:800:200C:417A]/'), 'http://[1080::8:800:200c:417a]/')
+
+  // IPv6address, examples from RFC 5952
+  t.equal(URI.normalize('//[2001:0db8::0001]/'), '//[2001:db8::1]/')
+  t.equal(URI.normalize('//[2001:db8::1:0000:1]/'), '//[2001:db8::1:0:1]/')
+  t.equal(URI.normalize('//[2001:db8:0:0:0:0:2:1]/'), '//[2001:db8::2:1]/')
+  t.equal(URI.normalize('//[2001:db8:0:1:1:1:1:1]/'), '//[2001:db8:0:1:1:1:1:1]/')
+  t.equal(URI.normalize('//[2001:0:0:1:0:0:0:1]/'), '//[2001:0:0:1::1]/')
+  t.equal(URI.normalize('//[2001:db8:0:0:1:0:0:1]/'), '//[2001:db8::1:0:0:1]/')
+  t.equal(URI.normalize('//[2001:DB8::1]/'), '//[2001:db8::1]/')
+  t.equal(URI.normalize('//[0:0:0:0:0:ffff:192.0.2.1]/'), '//[::ffff:192.0.2.1]/')
+
+  // Mixed IPv4 and IPv6 address
+  t.equal(URI.normalize('//[1:2:3:4:5:6:192.0.2.1]/'), '//[1:2:3:4:5:6:192.0.2.1]/')
+  t.equal(URI.normalize('//[1:2:3:4:5:6:192.068.001.000]/'), '//[1:2:3:4:5:6:192.68.1.0]/')
+
+  t.end()
+})
+
+test('URI Equals', (t) => {
+  // test from RFC 3986
+  t.equal(URI.equal('example://a/b/c/%7Bfoo%7D', 'eXAMPLE://a/./b/../b/%63/%7bfoo%7d'), true)
+
+  // test from RFC 3987
+  t.equal(URI.equal('http://example.org/~user', 'http://example.org/%7euser'), true)
+
+  t.end()
+})
+
+test('Escape Component', { skip: true }, (t) => {
+  let chr
+  for (let d = 0; d <= 129; ++d) {
+    chr = String.fromCharCode(d)
+    if (!chr.match(/[$&+,;=]/)) {
+      t.equal(URI.escapeComponent(chr), encodeURIComponent(chr))
+    } else {
+      t.equal(URI.escapeComponent(chr), chr)
+    }
+  }
+  t.equal(URI.escapeComponent('\u00c0'), encodeURIComponent('\u00c0'))
+  t.equal(URI.escapeComponent('\u07ff'), encodeURIComponent('\u07ff'))
+  t.equal(URI.escapeComponent('\u0800'), encodeURIComponent('\u0800'))
+  t.equal(URI.escapeComponent('\u30a2'), encodeURIComponent('\u30a2'))
+  t.end()
+})
+
+test('Unescape Component', { skip: true }, (t) => {
+  let chr
+  for (let d = 0; d <= 129; ++d) {
+    chr = String.fromCharCode(d)
+    t.equal(URI.unescapeComponent(encodeURIComponent(chr)), chr)
+  }
+  t.equal(URI.unescapeComponent(encodeURIComponent('\u00c0')), '\u00c0')
+  t.equal(URI.unescapeComponent(encodeURIComponent('\u07ff')), '\u07ff')
+  t.equal(URI.unescapeComponent(encodeURIComponent('\u0800')), '\u0800')
+  t.equal(URI.unescapeComponent(encodeURIComponent('\u30a2')), '\u30a2')
+  t.end()
+})
+
+const IRI_OPTION = { iri: true, unicodeSupport: true }
+
+test('IRI Parsing', { skip: true }, (t) => {
+  const components = URI.parse('uri://us\xA0er:pa\uD7FFss@example.com:123/o\uF900ne/t\uFDCFwo.t\uFDF0hree?q1=a1\uF8FF\uE000&q2=a2#bo\uFFEFdy', IRI_OPTION)
+  t.equal(components.error, undefined, 'all errors')
+  t.equal(components.scheme, 'uri', 'scheme')
+  t.equal(components.userinfo, 'us\xA0er:pa\uD7FFss', 'userinfo')
+  t.equal(components.host, 'example.com', 'host')
+  t.equal(components.port, 123, 'port')
+  t.equal(components.path, '/o\uF900ne/t\uFDCFwo.t\uFDF0hree', 'path')
+  t.equal(components.query, 'q1=a1\uF8FF\uE000&q2=a2', 'query')
+  t.equal(components.fragment, 'bo\uFFEFdy', 'fragment')
+  t.end()
+})
+
+test('IRI Serialization', { skip: true }, (t) => {
+  const components = {
+    scheme: 'uri',
+    userinfo: 'us\xA0er:pa\uD7FFss',
+    host: 'example.com',
+    port: 123,
+    path: '/o\uF900ne/t\uFDCFwo.t\uFDF0hree',
+    query: 'q1=a1\uF8FF\uE000&q2=a2',
+    fragment: 'bo\uFFEFdy\uE001'
+  }
+  t.equal(URI.serialize(components, IRI_OPTION), 'uri://us\xA0er:pa\uD7FFss@example.com:123/o\uF900ne/t\uFDCFwo.t\uFDF0hree?q1=a1\uF8FF\uE000&q2=a2#bo\uFFEFdy%EE%80%81')
+  t.end()
+})
+
+test('IRI Normalizing', { skip: true }, (t) => {
+  t.equal(URI.normalize('uri://www.example.org/red%09ros\xE9#red', IRI_OPTION), 'uri://www.example.org/red%09ros\xE9#red')
+  t.end()
+})
+
+test('IRI Equals', { skip: true }, (t) => {
+  // example from RFC 3987
+  t.equal(URI.equal('example://a/b/c/%7Bfoo%7D/ros\xE9', 'eXAMPLE://a/./b/../b/%63/%7bfoo%7d/ros%C3%A9', IRI_OPTION), true)
+  t.end()
+})
+
+test('Convert IRI to URI', { skip: true }, (t) => {
+  // example from RFC 3987
+  t.equal(URI.serialize(URI.parse('uri://www.example.org/red%09ros\xE9#red', IRI_OPTION)), 'uri://www.example.org/red%09ros%C3%A9#red')
+
+  // Internationalized Domain Name conversion via punycode example from RFC 3987
+  t.equal(URI.serialize(URI.parse('uri://r\xE9sum\xE9.example.org', { iri: true, domainHost: true }), { domainHost: true }), 'uri://xn--rsum-bpad.example.org')
+  t.end()
+})
+
+test('Convert URI to IRI', { skip: true }, (t) => {
+  // examples from RFC 3987
+  t.equal(URI.serialize(URI.parse('uri://www.example.org/D%C3%BCrst'), IRI_OPTION), 'uri://www.example.org/D\xFCrst')
+  t.equal(URI.serialize(URI.parse('uri://www.example.org/D%FCrst'), IRI_OPTION), 'uri://www.example.org/D%FCrst')
+  t.equal(URI.serialize(URI.parse('uri://xn--99zt52a.example.org/%e2%80%ae'), IRI_OPTION), 'uri://xn--99zt52a.example.org/%E2%80%AE') // or uri://\u7D0D\u8C46.example.org/%E2%80%AE
+
+  // Internationalized Domain Name conversion via punycode example from RFC 3987
+  t.equal(URI.serialize(URI.parse('uri://xn--rsum-bpad.example.org', { domainHost: true }), { iri: true, domainHost: true }), 'uri://r\xE9sum\xE9.example.org')
+  t.end()
+})
+
+if (URI.SCHEMES.http) {
+  test('HTTP Equals', (t) => {
+    // test from RFC 2616
+    t.equal(URI.equal('http://abc.com:80/~smith/home.html', 'http://abc.com/~smith/home.html'), true)
+    t.equal(URI.equal('http://ABC.com/%7Esmith/home.html', 'http://abc.com/~smith/home.html'), true)
+    t.equal(URI.equal('http://ABC.com:/%7esmith/home.html', 'http://abc.com/~smith/home.html'), true)
+    t.equal(URI.equal('HTTP://ABC.COM', 'http://abc.com/'), true)
+    // test from RFC 3986
+    t.equal(URI.equal('http://example.com:/', 'http://example.com:80/'), true)
+    t.end()
+  })
+}
+
+if (URI.SCHEMES.https) {
+  test('HTTPS Equals', (t) => {
+    t.equal(URI.equal('https://example.com', 'https://example.com:443/'), true)
+    t.equal(URI.equal('https://example.com:/', 'https://example.com:443/'), true)
+    t.end()
+  })
+}
+
+if (URI.SCHEMES.urn) {
+  test('URN Parsing', (t) => {
+    // example from RFC 2141
+    const components = URI.parse('urn:foo:a123,456')
+    t.equal(components.error, undefined, 'errors')
+    t.equal(components.scheme, 'urn', 'scheme')
+    t.equal(components.userinfo, undefined, 'userinfo')
+    t.equal(components.host, undefined, 'host')
+    t.equal(components.port, undefined, 'port')
+    t.equal(components.path, undefined, 'path')
+    t.equal(components.query, undefined, 'query')
+    t.equal(components.fragment, undefined, 'fragment')
+    t.equal(components.nid, 'foo', 'nid')
+    t.equal(components.nss, 'a123,456', 'nss')
+    t.end()
+  })
+
+  test('URN Serialization', (t) => {
+    // example from RFC 2141
+    const components = {
+      scheme: 'urn',
+      nid: 'foo',
+      nss: 'a123,456'
+    }
+    t.equal(URI.serialize(components), 'urn:foo:a123,456')
+    t.end()
+  })
+
+  test('URN Equals', { skip: true }, (t) => {
+    // test from RFC 2141
+    t.equal(URI.equal('urn:foo:a123,456', 'urn:foo:a123,456'), true)
+    t.equal(URI.equal('urn:foo:a123,456', 'URN:foo:a123,456'), true)
+    t.equal(URI.equal('urn:foo:a123,456', 'urn:FOO:a123,456'), true)
+    t.equal(URI.equal('urn:foo:a123,456', 'urn:foo:A123,456'), false)
+    t.equal(URI.equal('urn:foo:a123%2C456', 'URN:FOO:a123%2c456'), true)
+    t.end()
+  })
+
+  test('URN Resolving', (t) => {
+    // example from epoberezkin
+    t.equal(URI.resolve('', 'urn:some:ip:prop'), 'urn:some:ip:prop')
+    t.equal(URI.resolve('#', 'urn:some:ip:prop'), 'urn:some:ip:prop')
+    t.equal(URI.resolve('urn:some:ip:prop', 'urn:some:ip:prop'), 'urn:some:ip:prop')
+    t.equal(URI.resolve('urn:some:other:prop', 'urn:some:ip:prop'), 'urn:some:ip:prop')
+    t.end()
+  })
+
+  test('UUID Parsing', (t) => {
+    // example from RFC 4122
+    let components = URI.parse('urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6')
+    t.equal(components.error, undefined, 'errors')
+    t.equal(components.scheme, 'urn', 'scheme')
+    t.equal(components.userinfo, undefined, 'userinfo')
+    t.equal(components.host, undefined, 'host')
+    t.equal(components.port, undefined, 'port')
+    t.equal(components.path, undefined, 'path')
+    t.equal(components.query, undefined, 'query')
+    t.equal(components.fragment, undefined, 'fragment')
+    t.equal(components.nid, 'uuid', 'nid')
+    t.equal(components.nss, undefined, 'nss')
+    t.equal(components.uuid, 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6', 'uuid')
+
+    components = URI.parse('urn:uuid:notauuid-7dec-11d0-a765-00a0c91e6bf6')
+    t.notEqual(components.error, undefined, 'errors')
+    t.end()
+  })
+
+  test('UUID Serialization', (t) => {
+    // example from RFC 4122
+    let components = {
+      scheme: 'urn',
+      nid: 'uuid',
+      uuid: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6'
+    }
+    t.equal(URI.serialize(components), 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6')
+
+    components = {
+      scheme: 'urn',
+      nid: 'uuid',
+      uuid: 'notauuid-7dec-11d0-a765-00a0c91e6bf6'
+    }
+    t.equal(URI.serialize(components), 'urn:uuid:notauuid-7dec-11d0-a765-00a0c91e6bf6')
+    t.end()
+  })
+
+  test('UUID Equals', (t) => {
+    t.equal(URI.equal('URN:UUID:F81D4FAE-7DEC-11D0-A765-00A0C91E6BF6', 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6'), true)
+    t.end()
+  })
+
+  test('URN NID Override', (t) => {
+    let components = URI.parse('urn:foo:f81d4fae-7dec-11d0-a765-00a0c91e6bf6', { nid: 'uuid' })
+    t.equal(components.error, undefined, 'errors')
+    t.equal(components.scheme, 'urn', 'scheme')
+    t.equal(components.path, undefined, 'path')
+    t.equal(components.nid, 'foo', 'nid')
+    t.equal(components.nss, undefined, 'nss')
+    t.equal(components.uuid, 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6', 'uuid')
+
+    components = {
+      scheme: 'urn',
+      nid: 'foo',
+      uuid: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6'
+    }
+    t.equal(URI.serialize(components, { nid: 'uuid' }), 'urn:foo:f81d4fae-7dec-11d0-a765-00a0c91e6bf6')
+    t.end()
+  })
+}
+
+if (URI.SCHEMES.mailto) {
+  test('Mailto Parse', (t) => {
+    let components
+
+    // tests from RFC 6068
+
+    components = URI.parse('mailto:chris@example.com')
+    t.equal(components.error, undefined, 'error')
+    t.equal(components.scheme, 'mailto', 'scheme')
+    t.equal(components.userinfo, undefined, 'userinfo')
+    t.equal(components.host, undefined, 'host')
+    t.equal(components.port, undefined, 'port')
+    t.equal(components.path, undefined, 'path')
+    t.equal(components.query, undefined, 'query')
+    t.equal(components.fragment, undefined, 'fragment')
+    t.deepEqual(components.to, ['chris@example.com'], 'to')
+    t.equal(components.subject, undefined, 'subject')
+    t.equal(components.body, undefined, 'body')
+    t.equal(components.headers, undefined, 'headers')
+
+    components = URI.parse('mailto:infobot@example.com?subject=current-issue')
+    t.deepEqual(components.to, ['infobot@example.com'], 'to')
+    t.equal(components.subject, 'current-issue', 'subject')
+
+    components = URI.parse('mailto:infobot@example.com?body=send%20current-issue')
+    t.deepEqual(components.to, ['infobot@example.com'], 'to')
+    t.equal(components.body, 'send current-issue', 'body')
+
+    components = URI.parse('mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index')
+    t.deepEqual(components.to, ['infobot@example.com'], 'to')
+    t.equal(components.body, 'send current-issue\x0D\x0Asend index', 'body')
+
+    components = URI.parse('mailto:list@example.org?In-Reply-To=%3C3469A91.D10AF4C@example.com%3E')
+    t.deepEqual(components.to, ['list@example.org'], 'to')
+    t.deepEqual(components.headers, { 'In-Reply-To': '<3469A91.D10AF4C@example.com>' }, 'headers')
+
+    components = URI.parse('mailto:majordomo@example.com?body=subscribe%20bamboo-l')
+    t.deepEqual(components.to, ['majordomo@example.com'], 'to')
+    t.equal(components.body, 'subscribe bamboo-l', 'body')
+
+    components = URI.parse('mailto:joe@example.com?cc=bob@example.com&body=hello')
+    t.deepEqual(components.to, ['joe@example.com'], 'to')
+    t.equal(components.body, 'hello', 'body')
+    t.deepEqual(components.headers, { cc: 'bob@example.com' }, 'headers')
+
+    components = URI.parse('mailto:joe@example.com?cc=bob@example.com?body=hello')
+    if (URI.VALIDATE_SUPPORT) t.ok(components.error, 'invalid header fields')
+
+    components = URI.parse('mailto:gorby%25kremvax@example.com')
+    t.deepEqual(components.to, ['gorby%kremvax@example.com'], 'to gorby%kremvax@example.com')
+
+    components = URI.parse('mailto:unlikely%3Faddress@example.com?blat=foop')
+    t.deepEqual(components.to, ['unlikely?address@example.com'], 'to unlikely?address@example.com')
+    t.deepEqual(components.headers, { blat: 'foop' }, 'headers')
+
+    components = URI.parse('mailto:Mike%26family@example.org')
+    t.deepEqual(components.to, ['Mike&family@example.org'], 'to Mike&family@example.org')
+
+    components = URI.parse('mailto:%22not%40me%22@example.org')
+    t.deepEqual(components.to, ['"not@me"@example.org'], 'to ' + '"not@me"@example.org')
+
+    components = URI.parse('mailto:%22oh%5C%5Cno%22@example.org')
+    t.deepEqual(components.to, ['"oh\\\\no"@example.org'], 'to ' + '"oh\\\\no"@example.org')
+
+    components = URI.parse("mailto:%22%5C%5C%5C%22it's%5C%20ugly%5C%5C%5C%22%22@example.org")
+    t.deepEqual(components.to, ['"\\\\\\"it\'s\\ ugly\\\\\\""@example.org'], 'to ' + '"\\\\\\"it\'s\\ ugly\\\\\\""@example.org')
+
+    components = URI.parse('mailto:user@example.org?subject=caf%C3%A9')
+    t.deepEqual(components.to, ['user@example.org'], 'to')
+    t.equal(components.subject, 'caf\xE9', 'subject')
+
+    components = URI.parse('mailto:user@example.org?subject=%3D%3Futf-8%3FQ%3Fcaf%3DC3%3DA9%3F%3D')
+    t.deepEqual(components.to, ['user@example.org'], 'to')
+    t.equal(components.subject, '=?utf-8?Q?caf=C3=A9?=', 'subject') // TODO: Verify this
+
+    components = URI.parse('mailto:user@example.org?subject=%3D%3Fiso-8859-1%3FQ%3Fcaf%3DE9%3F%3D')
+    t.deepEqual(components.to, ['user@example.org'], 'to')
+    t.equal(components.subject, '=?iso-8859-1?Q?caf=E9?=', 'subject') // TODO: Verify this
+
+    components = URI.parse('mailto:user@example.org?subject=caf%C3%A9&body=caf%C3%A9')
+    t.deepEqual(components.to, ['user@example.org'], 'to')
+    t.equal(components.subject, 'caf\xE9', 'subject')
+    t.equal(components.body, 'caf\xE9', 'body')
+
+    if (URI.IRI_SUPPORT) {
+      components = URI.parse('mailto:user@%E7%B4%8D%E8%B1%86.example.org?subject=Test&body=NATTO')
+      t.deepEqual(components.to, ['user@xn--99zt52a.example.org'], 'to')
+      t.equal(components.subject, 'Test', 'subject')
+      t.equal(components.body, 'NATTO', 'body')
+    }
+
+    t.end()
+  })
+
+  test('Mailto Serialize', (t) => {
+    // tests from RFC 6068
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['chris@example.com'] }), 'mailto:chris@example.com')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['infobot@example.com'], body: 'current-issue' }), 'mailto:infobot@example.com?body=current-issue')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['infobot@example.com'], body: 'send current-issue' }), 'mailto:infobot@example.com?body=send%20current-issue')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['infobot@example.com'], body: 'send current-issue\x0D\x0Asend index' }), 'mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['list@example.org'], headers: { 'In-Reply-To': '<3469A91.D10AF4C@example.com>' } }), 'mailto:list@example.org?In-Reply-To=%3C3469A91.D10AF4C@example.com%3E')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['majordomo@example.com'], body: 'subscribe bamboo-l' }), 'mailto:majordomo@example.com?body=subscribe%20bamboo-l')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['joe@example.com'], headers: { cc: 'bob@example.com', body: 'hello' } }), 'mailto:joe@example.com?cc=bob@example.com&body=hello')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['gorby%25kremvax@example.com'] }), 'mailto:gorby%25kremvax@example.com')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['unlikely%3Faddress@example.com'], headers: { blat: 'foop' } }), 'mailto:unlikely%3Faddress@example.com?blat=foop')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['Mike&family@example.org'] }), 'mailto:Mike%26family@example.org')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['"not@me"@example.org'] }), 'mailto:%22not%40me%22@example.org')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['"oh\\\\no"@example.org'] }), 'mailto:%22oh%5C%5Cno%22@example.org')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['"\\\\\\"it\'s\\ ugly\\\\\\""@example.org'] }), "mailto:%22%5C%5C%5C%22it's%5C%20ugly%5C%5C%5C%22%22@example.org")
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['user@example.org'], subject: 'caf\xE9' }), 'mailto:user@example.org?subject=caf%C3%A9')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['user@example.org'], subject: '=?utf-8?Q?caf=C3=A9?=' }), 'mailto:user@example.org?subject=%3D%3Futf-8%3FQ%3Fcaf%3DC3%3DA9%3F%3D')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['user@example.org'], subject: '=?iso-8859-1?Q?caf=E9?=' }), 'mailto:user@example.org?subject=%3D%3Fiso-8859-1%3FQ%3Fcaf%3DE9%3F%3D')
+    t.equal(URI.serialize({ scheme: 'mailto', to: ['user@example.org'], subject: 'caf\xE9', body: 'caf\xE9' }), 'mailto:user@example.org?subject=caf%C3%A9&body=caf%C3%A9')
+    if (URI.IRI_SUPPORT) {
+      t.equal(URI.serialize({ scheme: 'mailto', to: ['us\xE9r@\u7d0d\u8c46.example.org'], subject: 'Test', body: 'NATTO' }), 'mailto:us%C3%A9r@xn--99zt52a.example.org?subject=Test&body=NATTO')
+    }
+    t.end()
+  })
+
+  test('Mailto Equals', (t) => {
+    // tests from RFC 6068
+    t.equal(URI.equal('mailto:addr1@an.example,addr2@an.example', 'mailto:?to=addr1@an.example,addr2@an.example'), true)
+    t.equal(URI.equal('mailto:?to=addr1@an.example,addr2@an.example', 'mailto:addr1@an.example?to=addr2@an.example'), true)
+    t.end()
+  })
+}
+
+if (URI.SCHEMES.ws) {
+  test('WS Parse', (t) => {
+    let components
+
+    // example from RFC 6455, Sec 4.1
+    components = URI.parse('ws://example.com/chat')
+    t.equal(components.error, undefined, 'error')
+    t.equal(components.scheme, 'ws', 'scheme')
+    t.equal(components.userinfo, undefined, 'userinfo')
+    t.equal(components.host, 'example.com', 'host')
+    t.equal(components.port, undefined, 'port')
+    t.equal(components.path, undefined, 'path')
+    t.equal(components.query, undefined, 'query')
+    t.equal(components.fragment, undefined, 'fragment')
+    t.equal(components.resourceName, '/chat', 'resourceName')
+    t.equal(components.secure, false, 'secure')
+
+    components = URI.parse('ws://example.com/foo?bar=baz')
+    t.equal(components.error, undefined, 'error')
+    t.equal(components.scheme, 'ws', 'scheme')
+    t.equal(components.userinfo, undefined, 'userinfo')
+    t.equal(components.host, 'example.com', 'host')
+    t.equal(components.port, undefined, 'port')
+    t.equal(components.path, undefined, 'path')
+    t.equal(components.query, undefined, 'query')
+    t.equal(components.fragment, undefined, 'fragment')
+    t.equal(components.resourceName, '/foo?bar=baz', 'resourceName')
+    t.equal(components.secure, false, 'secure')
+
+    components = URI.parse('ws://example.com/?bar=baz')
+    t.equal(components.resourceName, '/?bar=baz', 'resourceName')
+
+    t.end()
+  })
+
+  test('WS Serialize', (t) => {
+    t.equal(URI.serialize({ scheme: 'ws' }), 'ws:')
+    t.equal(URI.serialize({ scheme: 'ws', host: 'example.com' }), 'ws://example.com')
+    t.equal(URI.serialize({ scheme: 'ws', resourceName: '/' }), 'ws:')
+    t.equal(URI.serialize({ scheme: 'ws', resourceName: '/foo' }), 'ws:/foo')
+    t.equal(URI.serialize({ scheme: 'ws', resourceName: '/foo?bar' }), 'ws:/foo?bar')
+    t.equal(URI.serialize({ scheme: 'ws', secure: false }), 'ws:')
+    t.equal(URI.serialize({ scheme: 'ws', secure: true }), 'wss:')
+    t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo' }), 'ws://example.com/foo')
+    t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar' }), 'ws://example.com/foo?bar')
+    t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', secure: false }), 'ws://example.com')
+    t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', secure: true }), 'wss://example.com')
+    t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: false }), 'ws://example.com/foo?bar')
+    t.equal(URI.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: true }), 'wss://example.com/foo?bar')
+    t.end()
+  })
+
+  test('WS Equal', (t) => {
+    t.equal(URI.equal('WS://ABC.COM:80/chat#one', 'ws://abc.com/chat'), true)
+    t.end()
+  })
+
+  test('WS Normalize', (t) => {
+    t.equal(URI.normalize('ws://example.com:80/foo#hash'), 'ws://example.com/foo')
+    t.end()
+  })
+}
+
+if (URI.SCHEMES.wss) {
+  test('WSS Parse', (t) => {
+    let components
+
+    // example from RFC 6455, Sec 4.1
+    components = URI.parse('wss://example.com/chat')
+    t.equal(components.error, undefined, 'error')
+    t.equal(components.scheme, 'wss', 'scheme')
+    t.equal(components.userinfo, undefined, 'userinfo')
+    t.equal(components.host, 'example.com', 'host')
+    t.equal(components.port, undefined, 'port')
+    t.equal(components.path, undefined, 'path')
+    t.equal(components.query, undefined, 'query')
+    t.equal(components.fragment, undefined, 'fragment')
+    t.equal(components.resourceName, '/chat', 'resourceName')
+    t.equal(components.secure, true, 'secure')
+
+    components = URI.parse('wss://example.com/foo?bar=baz')
+    t.equal(components.error, undefined, 'error')
+    t.equal(components.scheme, 'wss', 'scheme')
+    t.equal(components.userinfo, undefined, 'userinfo')
+    t.equal(components.host, 'example.com', 'host')
+    t.equal(components.port, undefined, 'port')
+    t.equal(components.path, undefined, 'path')
+    t.equal(components.query, undefined, 'query')
+    t.equal(components.fragment, undefined, 'fragment')
+    t.equal(components.resourceName, '/foo?bar=baz', 'resourceName')
+    t.equal(components.secure, true, 'secure')
+
+    components = URI.parse('wss://example.com/?bar=baz')
+    t.equal(components.resourceName, '/?bar=baz', 'resourceName')
+
+    t.end()
+  })
+
+  test('WSS Serialize', (t) => {
+    t.equal(URI.serialize({ scheme: 'wss' }), 'wss:')
+    t.equal(URI.serialize({ scheme: 'wss', host: 'example.com' }), 'wss://example.com')
+    t.equal(URI.serialize({ scheme: 'wss', resourceName: '/' }), 'wss:')
+    t.equal(URI.serialize({ scheme: 'wss', resourceName: '/foo' }), 'wss:/foo')
+    t.equal(URI.serialize({ scheme: 'wss', resourceName: '/foo?bar' }), 'wss:/foo?bar')
+    t.equal(URI.serialize({ scheme: 'wss', secure: false }), 'ws:')
+    t.equal(URI.serialize({ scheme: 'wss', secure: true }), 'wss:')
+    t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo' }), 'wss://example.com/foo')
+    t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo?bar' }), 'wss://example.com/foo?bar')
+    t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', secure: false }), 'ws://example.com')
+    t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', secure: true }), 'wss://example.com')
+    t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo?bar', secure: false }), 'ws://example.com/foo?bar')
+    t.equal(URI.serialize({ scheme: 'wss', host: 'example.com', resourceName: '/foo?bar', secure: true }), 'wss://example.com/foo?bar')
+    t.end()
+  })
+
+  test('WSS Equal', (t) => {
+    t.equal(URI.equal('WSS://ABC.COM:443/chat#one', 'wss://abc.com/chat'), true)
+    t.end()
+  })
+
+  test('WSS Normalize', (t) => {
+    t.equal(URI.normalize('wss://example.com:443/foo#hash'), 'wss://example.com/foo')
+    t.end()
+  })
+}
Index: imaps-frontend/node_modules/fast-uri/test/util.test.js
===================================================================
--- imaps-frontend/node_modules/fast-uri/test/util.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/test/util.test.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,23 @@
+'use strict'
+
+const test = require('tape')
+const {
+  stringArrayToHexStripped
+} = require('../lib/utils')
+
+test('stringArrayToHexStripped', (t) => {
+  const testCases = [
+    [[['0', '0', '0', '0']], ''],
+    [[['0', '0', '0', '0'], false], ''],
+    [[['0', '0', '0', '0'], true], '0'],
+    [[['0', '1', '0', '0'], false], '100'],
+    [[['1', '0', '0', '0'], false], '1000'],
+    [[['1', '0', '0', '0'], true], '1000']
+  ]
+
+  t.plan(testCases.length)
+
+  testCases.forEach(([input, expected]) => {
+    t.same(stringArrayToHexStripped(input[0], input[1]), expected)
+  })
+})
Index: imaps-frontend/node_modules/fast-uri/types/index.d.ts
===================================================================
--- imaps-frontend/node_modules/fast-uri/types/index.d.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/types/index.d.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,53 @@
+type FastUri = typeof fastUri
+
+declare namespace fastUri {
+  export interface URIComponent {
+    scheme?: string;
+    userinfo?: string;
+    host?: string;
+    port?: number | string;
+    path?: string;
+    query?: string;
+    fragment?: string;
+    reference?: string;
+    error?: string;
+  }
+  export interface Options {
+    scheme?: string;
+    reference?: string;
+    unicodeSupport?: boolean;
+    domainHost?: boolean;
+    absolutePath?: boolean;
+    tolerant?: boolean;
+  }
+
+  /**
+   * @deprecated Use Options instead
+   */
+  export type options = Options
+  /**
+   * @deprecated Use URIComponent instead
+   */
+  export type URIComponents = URIComponent
+
+  export function normalize (uri: string, opts?: Options): string
+  export function normalize (uri: URIComponent, opts?: Options): URIComponent
+  export function normalize (uri: any, opts?: Options): any
+
+  export function resolve (baseURI: string, relativeURI: string, options?: Options): string
+
+  export function resolveComponent (base: URIComponent, relative: URIComponent, options?: Options, skipNormalization?: boolean): URIComponent
+
+  export function parse (uri: string, opts?: Options): URIComponent
+
+  export function serialize (component: URIComponent, opts?: Options): string
+
+  export function equal (uriA: string, uriB: string): boolean
+
+  export function resolve (base: string, path: string): string
+
+  export const fastUri: FastUri
+  export { fastUri as default }
+}
+
+export = fastUri
Index: imaps-frontend/node_modules/fast-uri/types/index.test-d.ts
===================================================================
--- imaps-frontend/node_modules/fast-uri/types/index.test-d.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/fast-uri/types/index.test-d.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,17 @@
+import uri, { URIComponents, URIComponent, Options, options } from '..'
+import { expectDeprecated, expectType } from 'tsd'
+
+const parsed = uri.parse('foo')
+expectType<URIComponents>(parsed)
+const parsed2 = uri.parse('foo', {
+  domainHost: true,
+  scheme: 'https',
+  unicodeSupport: false
+})
+expectType<URIComponents>(parsed2)
+
+expectType<URIComponent>({} as URIComponents)
+expectDeprecated({} as URIComponents)
+
+expectType<Options>({} as options)
+expectDeprecated({} as options)
