summary refs log tree commit diff
path: root/gateway
diff options
context:
space:
mode:
authorFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-08-12 20:18:05 +0200
committerFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-08-12 20:18:05 +0200
commitfa31e7f8db61efe085f7d8a317e6a8640ebb3f46 (patch)
tree5d12bfa42b9ed09e67935c1e6a5063babe33eeb8 /gateway
parentMerge branch 'master' into gateway (diff)
downloadserver-fa31e7f8db61efe085f7d8a317e6a8640ebb3f46.tar.xz
:sparkles: gateway
Diffstat (limited to 'gateway')
-rw-r--r--gateway/.env.example4
-rw-r--r--gateway/.github/FUNDING.yml1
-rw-r--r--gateway/.github/workflows/docker-publish.yml47
-rw-r--r--gateway/.gitignore107
-rw-r--r--gateway/.vscode/launch.json17
-rw-r--r--gateway/Dockerfile14
-rw-r--r--gateway/LICENSE14
-rw-r--r--gateway/README.md42
-rw-r--r--gateway/client.js51
-rw-r--r--gateway/package-lock.json4202
-rw-r--r--gateway/package.json38
-rw-r--r--gateway/src/Server.ts55
-rw-r--r--gateway/src/events/Close.ts6
-rw-r--r--gateway/src/events/Connection.ts62
-rw-r--r--gateway/src/events/Message.ts45
-rw-r--r--gateway/src/index.ts1
-rw-r--r--gateway/src/listener/listener.ts382
-rw-r--r--gateway/src/opcodes/Heartbeat.ts12
-rw-r--r--gateway/src/opcodes/Identify.ts174
-rw-r--r--gateway/src/opcodes/LazyRequest.ts105
-rw-r--r--gateway/src/opcodes/PresenceUpdate.ts6
-rw-r--r--gateway/src/opcodes/RequestGuildMembers.ts7
-rw-r--r--gateway/src/opcodes/Resume.ts14
-rw-r--r--gateway/src/opcodes/VoiceStateUpdate.ts26
-rw-r--r--gateway/src/opcodes/experiments.json76
-rw-r--r--gateway/src/opcodes/index.ts25
-rw-r--r--gateway/src/opcodes/instanceOf.ts18
-rw-r--r--gateway/src/schema/Activity.ts49
-rw-r--r--gateway/src/schema/Emoji.ts11
-rw-r--r--gateway/src/schema/Identify.ts83
-rw-r--r--gateway/src/schema/LazyRequest.ts19
-rw-r--r--gateway/src/schema/VoiceStateUpdate.ts.ts15
-rw-r--r--gateway/src/start.ts14
-rw-r--r--gateway/src/util/Config.ts41
-rw-r--r--gateway/src/util/Constants.ts50
-rw-r--r--gateway/src/util/Send.ts28
-rw-r--r--gateway/src/util/WebSocket.ts23
-rw-r--r--gateway/src/util/setHeartbeat.ts11
-rw-r--r--gateway/tsconfig.json72
39 files changed, 5967 insertions, 0 deletions
diff --git a/gateway/.env.example b/gateway/.env.example
new file mode 100644
index 00000000..0224de64
--- /dev/null
+++ b/gateway/.env.example
@@ -0,0 +1,4 @@
+MONGO_URL=mongodb://localhost/fosscord
+PORT=3002
+PRODUCTION=TRUE
+THREADS=# automatically use all available cores, only available if production = true
\ No newline at end of file
diff --git a/gateway/.github/FUNDING.yml b/gateway/.github/FUNDING.yml
new file mode 100644
index 00000000..f76b9015
--- /dev/null
+++ b/gateway/.github/FUNDING.yml
@@ -0,0 +1 @@
+open_collective: fosscord
\ No newline at end of file
diff --git a/gateway/.github/workflows/docker-publish.yml b/gateway/.github/workflows/docker-publish.yml
new file mode 100644
index 00000000..46d9d04d
--- /dev/null
+++ b/gateway/.github/workflows/docker-publish.yml
@@ -0,0 +1,47 @@
+name: docker-publish
+
+on:
+  push:
+    branches:
+      - 'master'
+
+jobs:
+  docker:
+    runs-on: ubuntu-latest
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v2
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v1
+      -
+        name: Cache Docker layers
+        uses: actions/cache@v2
+        with:
+          path: /tmp/.buildx-cache
+          key: ${{ runner.os }}-buildx-${{ github.sha }}
+          restore-keys: |
+            ${{ runner.os }}-buildx-
+      -
+        name: Login to DockerHub
+        uses: docker/login-action@v1
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      -
+        name: Build and push
+        uses: docker/build-push-action@v2
+        with:
+          context: .
+          push: true
+          tags: ${{ secrets.DOCKERHUB_TAGS }}
+          cache-from: type=local,src=/tmp/.buildx-cache
+          cache-to: type=local,dest=/tmp/.buildx-cache-new
+      -
+        # Hackfix to cleanup cache; replace after buildx 0.6 and BuildKit 0.9 are released
+        # https://github.com/docker/build-push-action/pull/406#issuecomment-879184394
+        name: Move cache fix
+        run: |
+          rm -rf /tmp/.buildx-cache
+          mv /tmp/.buildx-cache-new /tmp/.buildx-cache
diff --git a/gateway/.gitignore b/gateway/.gitignore
new file mode 100644
index 00000000..daf8591a
--- /dev/null
+++ b/gateway/.gitignore
@@ -0,0 +1,107 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# TypeScript v1 declaration files
+typings/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+.env.test
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+
+# Next.js build output
+.next
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and *not* Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+.DS_Store
+
+data
\ No newline at end of file
diff --git a/gateway/.vscode/launch.json b/gateway/.vscode/launch.json
new file mode 100644
index 00000000..29bdde13
--- /dev/null
+++ b/gateway/.vscode/launch.json
@@ -0,0 +1,17 @@
+{
+	// Use IntelliSense to learn about possible attributes.
+	// Hover to view descriptions of existing attributes.
+	// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+	"version": "0.2.0",
+	"configurations": [
+		{
+			"sourceMaps": true,
+			"type": "node",
+			"request": "launch",
+			"name": "Launch Server",
+			"program": "${workspaceFolder}/dist/start.js",
+			"preLaunchTask": "tsc: build - tsconfig.json",
+			"outFiles": ["${workspaceFolder}/dist/**/*.js"]
+		}
+	]
+}
diff --git a/gateway/Dockerfile b/gateway/Dockerfile
new file mode 100644
index 00000000..e07b7d8f
--- /dev/null
+++ b/gateway/Dockerfile
@@ -0,0 +1,14 @@
+FROM node:lts-alpine
+WORKDIR /usr/src/fosscord-gateway
+COPY package.json .
+COPY package-lock.json .
+RUN apk --no-cache --virtual build-dependencies add \
+    python \
+    make \
+    g++
+RUN npm install
+RUN apk del build-dependencies
+COPY . .
+RUN npm run build
+EXPOSE 3002
+CMD ["node", "dist/start.js"]
diff --git a/gateway/LICENSE b/gateway/LICENSE
new file mode 100644
index 00000000..f19bf520
--- /dev/null
+++ b/gateway/LICENSE
@@ -0,0 +1,14 @@
+Copyright (C) 2021 Fosscord and contributors
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
\ No newline at end of file
diff --git a/gateway/README.md b/gateway/README.md
new file mode 100644
index 00000000..9ae6a5f1
--- /dev/null
+++ b/gateway/README.md
@@ -0,0 +1,42 @@
+<p align="center">
+  <img width="100" src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets/logo_big_transparent.png" />
+</p>
+<h1 align="center">Fosscord WebSocket Gateway Server</h1>
+
+<p>
+  <a href="https://discord.gg/ZrnGQP6p3d"><img src="https://img.shields.io/discord/806142446094385153?color=7489d5&logo=discord&logoColor=ffffff" /></a>
+  <img src="https://img.shields.io/static/v1?label=Status&message=Development&color=blue">
+  <a title="Crowdin" target="_blank" href="https://translate.fosscord.com/"><img src="https://badges.crowdin.net/fosscord/localized.svg"></a>
+  <a href="https://opencollective.com/fosscord"><img src="https://opencollective.com/fosscord/tiers/badge.svg"></a>
+</p>
+
+## [About](https://github.com/fosscord/fosscord-gateway/wiki)
+
+Fosscord is **f**ree **o**pen **s**ource **s**oftware compatible to dis**cord**. It is a selfhostable Chat, Voice and Video platform similar to Slack, Rocket.chat and Discord-compatible.
+
+-   Discord-compatible
+-   Selfhostable
+-   Open Source
+-   Configurable
+-   Secure
+-   Decentralized
+-   Extendable
+-   Themeable
+
+logo by [@nwlandas](https://twitter.com/nwlandas)
+
+## Installation
+
+_it is in development and not yet finished_
+
+## Support
+
+https://discord.gg/ZrnGQP6p3d
+
+if we are finished we'll host our own support server.
+
+## Contribute
+
+This project is only possible by volunteers like you and me, your contribution is very much appreciated 🥺.
+
+If you want to make this project reality and and you would like to contribute then [read the wiki](https://github.com/fosscord/fosscord-gateway/wiki) first.
diff --git a/gateway/client.js b/gateway/client.js
new file mode 100644
index 00000000..34a59458
--- /dev/null
+++ b/gateway/client.js
@@ -0,0 +1,51 @@
+require("missing-native-js-functions");
+const WebSocket = require("ws");
+const Constants = require("./dist/util/Constants");
+
+// const ws = new WebSocket("ws://127.0.0.1:8080");
+const ws = new WebSocket("wss://gateway.discord.gg");
+
+ws.on("open", () => {
+	// ws.send(JSON.stringify({ req_type: "new_auth" }));
+	// ws.send(JSON.stringify({ req_type: "check_auth", token: "" }));
+	// op: 0,
+	// d: {},
+	// s: 42,
+	// t: "GATEWAY_EVENT_NAME",
+});
+
+function send(data) {
+	ws.send(JSON.stringify(data));
+}
+
+ws.on("message", (buffer) => {
+	let data = JSON.parse(buffer.toString());
+	console.log(data);
+
+	switch (data.op) {
+		case 10:
+			setIntervalNow(() => {
+				send({ op: 1 });
+			}, data.d.heartbeat_interval);
+
+			// send({
+			// 	op: 2,
+			// 	d: {
+			// 		token:
+			// 			"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjgxMTY0MjkxNzQzMjA2NjA0OCIsImlhdCI6MTYxMzU4MTE1MX0.7Qj_z2lYIgJ0rc7NfGtpW5DKGqecQfv1mLpoBUQHKDc",
+			// 		intents: 0n,
+			// 		properties: {},
+			// 	},
+			// });
+
+			send({
+				op: 6,
+			});
+
+			break;
+	}
+});
+
+ws.on("close", (code, reason) => {
+	console.log(code, reason, Constants.CLOSECODES[code]);
+});
diff --git a/gateway/package-lock.json b/gateway/package-lock.json
new file mode 100644
index 00000000..f3b31763
--- /dev/null
+++ b/gateway/package-lock.json
@@ -0,0 +1,4202 @@
+{
+	"name": "@fosscord/gateway",
+	"version": "1.0.0",
+	"lockfileVersion": 2,
+	"requires": true,
+	"packages": {
+		"": {
+			"name": "@fosscord/gateway",
+			"version": "1.0.0",
+			"license": "ISC",
+			"dependencies": {
+				"@fosscord/server-util": "^1.3.51",
+				"ajv": "^8.5.0",
+				"amqplib": "^0.8.0",
+				"dotenv": "^8.2.0",
+				"jsonwebtoken": "^8.5.1",
+				"lambert-server": "^1.2.8",
+				"missing-native-js-functions": "^1.2.3",
+				"mongoose-autopopulate": "^0.12.3",
+				"node-fetch": "^2.6.1",
+				"typescript": "^4.2.3",
+				"uuid": "^8.3.2",
+				"ws": "^7.4.2"
+			},
+			"devDependencies": {
+				"@types/amqplib": "^0.8.1",
+				"@types/jsonwebtoken": "^8.5.0",
+				"@types/mongoose-autopopulate": "^0.10.1",
+				"@types/uuid": "^8.3.0",
+				"@types/ws": "^7.4.0",
+				"erlpack": "^0.1.3",
+				"ts-node-dev": "^1.1.6"
+			}
+		},
+		"node_modules/@fosscord/server-util": {
+			"version": "1.3.51",
+			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.51.tgz",
+			"integrity": "sha512-z7gAwj8UFTrbabtyMqb/7mhiTTpk07dKMu2ZaL4yeTPBR2Ppnkd3JqYHcrqIyMfeENgzTFoOVSjtun1aFUFDag==",
+			"dependencies": {
+				"@types/jsonwebtoken": "^8.5.0",
+				"@types/mongoose-autopopulate": "^0.10.1",
+				"@types/mongoose-lean-virtuals": "^0.5.1",
+				"@types/node": "^14.14.25",
+				"ajv": "^8.5.0",
+				"amqplib": "^0.8.0",
+				"dot-prop": "^6.0.1",
+				"env-paths": "^2.2.1",
+				"jsonwebtoken": "^8.5.1",
+				"missing-native-js-functions": "^1.2.2",
+				"mongodb": "^3.6.9",
+				"mongoose": "^5.12.3",
+				"mongoose-autopopulate": "^0.12.3",
+				"typescript": "^4.1.3"
+			}
+		},
+		"node_modules/@types/amqplib": {
+			"version": "0.8.1",
+			"resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.8.1.tgz",
+			"integrity": "sha512-8dCjF+dHZ8Y6JOoHD1BMnxP0quAncvZq4wA/lS072NjX9vIzVRSMcmfKy2Os8ZQ8VWWp74MD09GMbVbKS6/Fxw==",
+			"dev": true,
+			"dependencies": {
+				"@types/bluebird": "*",
+				"@types/node": "*"
+			}
+		},
+		"node_modules/@types/bluebird": {
+			"version": "3.5.36",
+			"resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz",
+			"integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==",
+			"dev": true
+		},
+		"node_modules/@types/bson": {
+			"version": "4.0.3",
+			"resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz",
+			"integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==",
+			"dependencies": {
+				"@types/node": "*"
+			}
+		},
+		"node_modules/@types/jsonwebtoken": {
+			"version": "8.5.1",
+			"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+			"integrity": "sha512-rNAPdomlIUX0i0cg2+I+Q1wOUr531zHBQ+cV/28PJ39bSPKjahatZZ2LMuhiguETkCgLVzfruw/ZvNMNkKoSzw==",
+			"dependencies": {
+				"@types/node": "*"
+			}
+		},
+		"node_modules/@types/mongodb": {
+			"version": "3.6.17",
+			"resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.17.tgz",
+			"integrity": "sha512-9hhgvYPdC5iHyyksPcKCu45gfaAIPQHKHGdvNXu4582DmOZX3wrUJIJPT40o4G1oTKPgpMMFqZglOTjhnYoF+A==",
+			"dependencies": {
+				"@types/bson": "*",
+				"@types/node": "*"
+			}
+		},
+		"node_modules/@types/mongoose": {
+			"version": "5.10.5",
+			"resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.10.5.tgz",
+			"integrity": "sha512-37QMIA954T3n+HSksSNLlxZsqF8fMJu5S4dyPBod6gRxGtsXlQ9jUtL8BE8Seimv99u79eLXI3bggoCnSQ/fxQ==",
+			"dependencies": {
+				"@types/mongodb": "*",
+				"@types/node": "*"
+			}
+		},
+		"node_modules/@types/mongoose-autopopulate": {
+			"version": "0.10.1",
+			"resolved": "https://registry.npmjs.org/@types/mongoose-autopopulate/-/mongoose-autopopulate-0.10.1.tgz",
+			"integrity": "sha512-L67MAIE3WEoTtt7a7/spRYk+76lgp67FAP6I38Y9NcC1kQuzwqnukTaJzodfb8180wxHZM4qt68u6x6ptuDRaQ==",
+			"dependencies": {
+				"@types/mongoose": "*"
+			}
+		},
+		"node_modules/@types/mongoose-lean-virtuals": {
+			"version": "0.5.1",
+			"resolved": "https://registry.npmjs.org/@types/mongoose-lean-virtuals/-/mongoose-lean-virtuals-0.5.1.tgz",
+			"integrity": "sha512-bNk+QLjP5VZU4EsJag4xQsjLAa8CEm/SKZDyiC2kM208wIrGum6daD7j45Oqs50bWNGfqZYRuEhh8xZ17D7aEw==",
+			"dependencies": {
+				"@types/mongoose": "*"
+			}
+		},
+		"node_modules/@types/node": {
+			"version": "14.17.1",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.1.tgz",
+			"integrity": "sha512-/tpUyFD7meeooTRwl3sYlihx2BrJE7q9XF71EguPFIySj9B7qgnRtHsHTho+0AUm4m1SvWGm6uSncrR94q6Vtw=="
+		},
+		"node_modules/@types/strip-bom": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
+			"integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
+			"dev": true
+		},
+		"node_modules/@types/strip-json-comments": {
+			"version": "0.0.30",
+			"resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
+			"integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
+			"dev": true
+		},
+		"node_modules/@types/uuid": {
+			"version": "8.3.0",
+			"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz",
+			"integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==",
+			"dev": true
+		},
+		"node_modules/@types/ws": {
+			"version": "7.4.4",
+			"resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.4.tgz",
+			"integrity": "sha512-d/7W23JAXPodQNbOZNXvl2K+bqAQrCMwlh/nuQsPSQk6Fq0opHoPrUw43aHsvSbIiQPr8Of2hkFbnz1XBFVyZQ==",
+			"dev": true,
+			"dependencies": {
+				"@types/node": "*"
+			}
+		},
+		"node_modules/accepts": {
+			"version": "1.3.7",
+			"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+			"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+			"dependencies": {
+				"mime-types": "~2.1.24",
+				"negotiator": "0.6.2"
+			},
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/ajv": {
+			"version": "8.5.0",
+			"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz",
+			"integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==",
+			"dependencies": {
+				"fast-deep-equal": "^3.1.1",
+				"json-schema-traverse": "^1.0.0",
+				"require-from-string": "^2.0.2",
+				"uri-js": "^4.2.2"
+			},
+			"funding": {
+				"type": "github",
+				"url": "https://github.com/sponsors/epoberezkin"
+			}
+		},
+		"node_modules/amqplib": {
+			"version": "0.8.0",
+			"resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.8.0.tgz",
+			"integrity": "sha512-icU+a4kkq4Y1PS4NNi+YPDMwdlbFcZ1EZTQT2nigW3fvOb6AOgUQ9+Mk4ue0Zu5cBg/XpDzB40oH10ysrk2dmA==",
+			"dependencies": {
+				"bitsyntax": "~0.1.0",
+				"bluebird": "^3.7.2",
+				"buffer-more-ints": "~1.0.0",
+				"readable-stream": "1.x >=1.1.9",
+				"safe-buffer": "~5.2.1",
+				"url-parse": "~1.5.1"
+			},
+			"engines": {
+				"node": ">=10"
+			}
+		},
+		"node_modules/amqplib/node_modules/bluebird": {
+			"version": "3.7.2",
+			"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+			"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+		},
+		"node_modules/amqplib/node_modules/isarray": {
+			"version": "0.0.1",
+			"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+			"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+		},
+		"node_modules/amqplib/node_modules/readable-stream": {
+			"version": "1.1.14",
+			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+			"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+			"dependencies": {
+				"core-util-is": "~1.0.0",
+				"inherits": "~2.0.1",
+				"isarray": "0.0.1",
+				"string_decoder": "~0.10.x"
+			}
+		},
+		"node_modules/amqplib/node_modules/string_decoder": {
+			"version": "0.10.31",
+			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+			"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+		},
+		"node_modules/ansi-styles": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+			"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+			"dependencies": {
+				"color-convert": "^2.0.1"
+			},
+			"engines": {
+				"node": ">=8"
+			},
+			"funding": {
+				"url": "https://github.com/chalk/ansi-styles?sponsor=1"
+			}
+		},
+		"node_modules/anymatch": {
+			"version": "3.1.2",
+			"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+			"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+			"dev": true,
+			"dependencies": {
+				"normalize-path": "^3.0.0",
+				"picomatch": "^2.0.4"
+			},
+			"engines": {
+				"node": ">= 8"
+			}
+		},
+		"node_modules/arg": {
+			"version": "4.1.3",
+			"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+			"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+			"dev": true
+		},
+		"node_modules/array-find-index": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+			"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/array-flatten": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+			"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+		},
+		"node_modules/balanced-match": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+			"dev": true
+		},
+		"node_modules/binary-extensions": {
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+			"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+			"dev": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/bindings": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+			"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+			"dev": true,
+			"dependencies": {
+				"file-uri-to-path": "1.0.0"
+			}
+		},
+		"node_modules/bitsyntax": {
+			"version": "0.1.0",
+			"resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz",
+			"integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==",
+			"dependencies": {
+				"buffer-more-ints": "~1.0.0",
+				"debug": "~2.6.9",
+				"safe-buffer": "~5.1.2"
+			},
+			"engines": {
+				"node": ">=0.8"
+			}
+		},
+		"node_modules/bitsyntax/node_modules/safe-buffer": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+		},
+		"node_modules/bl": {
+			"version": "2.2.1",
+			"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
+			"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
+			"dependencies": {
+				"readable-stream": "^2.3.5",
+				"safe-buffer": "^5.1.1"
+			}
+		},
+		"node_modules/bluebird": {
+			"version": "3.5.1",
+			"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
+			"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
+		},
+		"node_modules/body-parser": {
+			"version": "1.19.0",
+			"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+			"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+			"dependencies": {
+				"bytes": "3.1.0",
+				"content-type": "~1.0.4",
+				"debug": "2.6.9",
+				"depd": "~1.1.2",
+				"http-errors": "1.7.2",
+				"iconv-lite": "0.4.24",
+				"on-finished": "~2.3.0",
+				"qs": "6.7.0",
+				"raw-body": "2.4.0",
+				"type-is": "~1.6.17"
+			},
+			"engines": {
+				"node": ">= 0.8"
+			}
+		},
+		"node_modules/brace-expansion": {
+			"version": "1.1.11",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+			"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+			"dev": true,
+			"dependencies": {
+				"balanced-match": "^1.0.0",
+				"concat-map": "0.0.1"
+			}
+		},
+		"node_modules/braces": {
+			"version": "3.0.2",
+			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+			"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+			"dev": true,
+			"dependencies": {
+				"fill-range": "^7.0.1"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/bson": {
+			"version": "1.1.6",
+			"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
+			"integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
+			"engines": {
+				"node": ">=0.6.19"
+			}
+		},
+		"node_modules/buffer-equal-constant-time": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+			"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+		},
+		"node_modules/buffer-from": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+			"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+			"dev": true
+		},
+		"node_modules/buffer-more-ints": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
+			"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
+		},
+		"node_modules/bytes": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+			"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+			"engines": {
+				"node": ">= 0.8"
+			}
+		},
+		"node_modules/camelcase": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+			"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/camelcase-keys": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+			"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+			"dev": true,
+			"dependencies": {
+				"camelcase": "^2.0.0",
+				"map-obj": "^1.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/chalk": {
+			"version": "4.1.1",
+			"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
+			"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
+			"dependencies": {
+				"ansi-styles": "^4.1.0",
+				"supports-color": "^7.1.0"
+			},
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/chalk/chalk?sponsor=1"
+			}
+		},
+		"node_modules/chokidar": {
+			"version": "3.5.1",
+			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
+			"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
+			"dev": true,
+			"dependencies": {
+				"anymatch": "~3.1.1",
+				"braces": "~3.0.2",
+				"glob-parent": "~5.1.0",
+				"is-binary-path": "~2.1.0",
+				"is-glob": "~4.0.1",
+				"normalize-path": "~3.0.0",
+				"readdirp": "~3.5.0"
+			},
+			"engines": {
+				"node": ">= 8.10.0"
+			},
+			"optionalDependencies": {
+				"fsevents": "~2.3.1"
+			}
+		},
+		"node_modules/color-convert": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+			"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+			"dependencies": {
+				"color-name": "~1.1.4"
+			},
+			"engines": {
+				"node": ">=7.0.0"
+			}
+		},
+		"node_modules/color-name": {
+			"version": "1.1.4",
+			"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+			"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+		},
+		"node_modules/concat-map": {
+			"version": "0.0.1",
+			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+			"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+			"dev": true
+		},
+		"node_modules/content-disposition": {
+			"version": "0.5.3",
+			"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+			"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+			"dependencies": {
+				"safe-buffer": "5.1.2"
+			},
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/content-disposition/node_modules/safe-buffer": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+		},
+		"node_modules/content-type": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+			"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/cookie": {
+			"version": "0.4.0",
+			"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+			"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/cookie-signature": {
+			"version": "1.0.6",
+			"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+			"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+		},
+		"node_modules/core-util-is": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+			"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+		},
+		"node_modules/create-require": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+			"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
+			"dev": true
+		},
+		"node_modules/currently-unhandled": {
+			"version": "0.4.1",
+			"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+			"integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+			"dev": true,
+			"dependencies": {
+				"array-find-index": "^1.0.1"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/dateformat": {
+			"version": "1.0.12",
+			"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+			"integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+			"dev": true,
+			"dependencies": {
+				"get-stdin": "^4.0.1",
+				"meow": "^3.3.0"
+			},
+			"bin": {
+				"dateformat": "bin/cli.js"
+			},
+			"engines": {
+				"node": "*"
+			}
+		},
+		"node_modules/debug": {
+			"version": "2.6.9",
+			"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+			"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+			"dependencies": {
+				"ms": "2.0.0"
+			}
+		},
+		"node_modules/debug/node_modules/ms": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+			"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+		},
+		"node_modules/decamelize": {
+			"version": "1.2.0",
+			"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+			"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/denque": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
+			"integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==",
+			"engines": {
+				"node": ">=0.10"
+			}
+		},
+		"node_modules/depd": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+			"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/destroy": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+			"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+		},
+		"node_modules/diff": {
+			"version": "4.0.2",
+			"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+			"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.3.1"
+			}
+		},
+		"node_modules/dot-prop": {
+			"version": "6.0.1",
+			"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
+			"integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
+			"dependencies": {
+				"is-obj": "^2.0.0"
+			},
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/dotenv": {
+			"version": "8.6.0",
+			"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
+			"integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==",
+			"engines": {
+				"node": ">=10"
+			}
+		},
+		"node_modules/dynamic-dedupe": {
+			"version": "0.3.0",
+			"resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
+			"integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
+			"dev": true,
+			"dependencies": {
+				"xtend": "^4.0.0"
+			}
+		},
+		"node_modules/ecdsa-sig-formatter": {
+			"version": "1.0.11",
+			"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+			"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+			"dependencies": {
+				"safe-buffer": "^5.0.1"
+			}
+		},
+		"node_modules/ee-first": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+			"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+		},
+		"node_modules/encodeurl": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+			"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+			"engines": {
+				"node": ">= 0.8"
+			}
+		},
+		"node_modules/env-paths": {
+			"version": "2.2.1",
+			"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+			"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+			"engines": {
+				"node": ">=6"
+			}
+		},
+		"node_modules/erlpack": {
+			"version": "0.1.3",
+			"resolved": "https://registry.npmjs.org/erlpack/-/erlpack-0.1.3.tgz",
+			"integrity": "sha512-QeG9v8CVsY/a/IoQi8zjn23aYKcziOihAxwjUl3tI/KB4R1FjTtctDAAMovgtpC16S+WiOauers2oWwIOQtKBQ==",
+			"dev": true,
+			"hasInstallScript": true,
+			"dependencies": {
+				"bindings": "^1.5.0",
+				"nan": "^2.14.0"
+			}
+		},
+		"node_modules/error-ex": {
+			"version": "1.3.2",
+			"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+			"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+			"dev": true,
+			"dependencies": {
+				"is-arrayish": "^0.2.1"
+			}
+		},
+		"node_modules/escape-html": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+			"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+		},
+		"node_modules/etag": {
+			"version": "1.8.1",
+			"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+			"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/express": {
+			"version": "4.17.1",
+			"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+			"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+			"dependencies": {
+				"accepts": "~1.3.7",
+				"array-flatten": "1.1.1",
+				"body-parser": "1.19.0",
+				"content-disposition": "0.5.3",
+				"content-type": "~1.0.4",
+				"cookie": "0.4.0",
+				"cookie-signature": "1.0.6",
+				"debug": "2.6.9",
+				"depd": "~1.1.2",
+				"encodeurl": "~1.0.2",
+				"escape-html": "~1.0.3",
+				"etag": "~1.8.1",
+				"finalhandler": "~1.1.2",
+				"fresh": "0.5.2",
+				"merge-descriptors": "1.0.1",
+				"methods": "~1.1.2",
+				"on-finished": "~2.3.0",
+				"parseurl": "~1.3.3",
+				"path-to-regexp": "0.1.7",
+				"proxy-addr": "~2.0.5",
+				"qs": "6.7.0",
+				"range-parser": "~1.2.1",
+				"safe-buffer": "5.1.2",
+				"send": "0.17.1",
+				"serve-static": "1.14.1",
+				"setprototypeof": "1.1.1",
+				"statuses": "~1.5.0",
+				"type-is": "~1.6.18",
+				"utils-merge": "1.0.1",
+				"vary": "~1.1.2"
+			},
+			"engines": {
+				"node": ">= 0.10.0"
+			}
+		},
+		"node_modules/express-async-errors": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz",
+			"integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==",
+			"peerDependencies": {
+				"express": "^4.16.2"
+			}
+		},
+		"node_modules/express/node_modules/safe-buffer": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+		},
+		"node_modules/fast-deep-equal": {
+			"version": "3.1.3",
+			"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+		},
+		"node_modules/file-uri-to-path": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+			"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+			"dev": true
+		},
+		"node_modules/fill-range": {
+			"version": "7.0.1",
+			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+			"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+			"dev": true,
+			"dependencies": {
+				"to-regex-range": "^5.0.1"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/finalhandler": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+			"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+			"dependencies": {
+				"debug": "2.6.9",
+				"encodeurl": "~1.0.2",
+				"escape-html": "~1.0.3",
+				"on-finished": "~2.3.0",
+				"parseurl": "~1.3.3",
+				"statuses": "~1.5.0",
+				"unpipe": "~1.0.0"
+			},
+			"engines": {
+				"node": ">= 0.8"
+			}
+		},
+		"node_modules/find-up": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+			"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+			"dev": true,
+			"dependencies": {
+				"path-exists": "^2.0.0",
+				"pinkie-promise": "^2.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/forwarded": {
+			"version": "0.2.0",
+			"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+			"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/fresh": {
+			"version": "0.5.2",
+			"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+			"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/fs.realpath": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+			"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+			"dev": true
+		},
+		"node_modules/fsevents": {
+			"version": "2.3.2",
+			"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+			"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+			"dev": true,
+			"hasInstallScript": true,
+			"optional": true,
+			"os": [
+				"darwin"
+			],
+			"engines": {
+				"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+			}
+		},
+		"node_modules/function-bind": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+			"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+			"dev": true
+		},
+		"node_modules/get-stdin": {
+			"version": "4.0.1",
+			"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+			"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/glob": {
+			"version": "7.1.7",
+			"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+			"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+			"dev": true,
+			"dependencies": {
+				"fs.realpath": "^1.0.0",
+				"inflight": "^1.0.4",
+				"inherits": "2",
+				"minimatch": "^3.0.4",
+				"once": "^1.3.0",
+				"path-is-absolute": "^1.0.0"
+			},
+			"engines": {
+				"node": "*"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/isaacs"
+			}
+		},
+		"node_modules/glob-parent": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+			"dev": true,
+			"dependencies": {
+				"is-glob": "^4.0.1"
+			},
+			"engines": {
+				"node": ">= 6"
+			}
+		},
+		"node_modules/graceful-fs": {
+			"version": "4.2.6",
+			"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
+			"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
+			"dev": true
+		},
+		"node_modules/has": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+			"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+			"dev": true,
+			"dependencies": {
+				"function-bind": "^1.1.1"
+			},
+			"engines": {
+				"node": ">= 0.4.0"
+			}
+		},
+		"node_modules/has-flag": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+			"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/helmet": {
+			"version": "4.6.0",
+			"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz",
+			"integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg==",
+			"engines": {
+				"node": ">=10.0.0"
+			}
+		},
+		"node_modules/hosted-git-info": {
+			"version": "2.8.9",
+			"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+			"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+			"dev": true
+		},
+		"node_modules/http-errors": {
+			"version": "1.7.2",
+			"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+			"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+			"dependencies": {
+				"depd": "~1.1.2",
+				"inherits": "2.0.3",
+				"setprototypeof": "1.1.1",
+				"statuses": ">= 1.5.0 < 2",
+				"toidentifier": "1.0.0"
+			},
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/iconv-lite": {
+			"version": "0.4.24",
+			"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+			"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+			"dependencies": {
+				"safer-buffer": ">= 2.1.2 < 3"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/indent-string": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+			"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+			"dev": true,
+			"dependencies": {
+				"repeating": "^2.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/inflight": {
+			"version": "1.0.6",
+			"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+			"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+			"dev": true,
+			"dependencies": {
+				"once": "^1.3.0",
+				"wrappy": "1"
+			}
+		},
+		"node_modules/inherits": {
+			"version": "2.0.3",
+			"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+			"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+		},
+		"node_modules/ipaddr.js": {
+			"version": "1.9.1",
+			"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+			"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+			"engines": {
+				"node": ">= 0.10"
+			}
+		},
+		"node_modules/is-arrayish": {
+			"version": "0.2.1",
+			"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+			"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+			"dev": true
+		},
+		"node_modules/is-binary-path": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+			"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+			"dev": true,
+			"dependencies": {
+				"binary-extensions": "^2.0.0"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/is-core-module": {
+			"version": "2.4.0",
+			"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
+			"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
+			"dev": true,
+			"dependencies": {
+				"has": "^1.0.3"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/ljharb"
+			}
+		},
+		"node_modules/is-extglob": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+			"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/is-finite": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
+			"integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/is-glob": {
+			"version": "4.0.1",
+			"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+			"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+			"dev": true,
+			"dependencies": {
+				"is-extglob": "^2.1.1"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/is-number": {
+			"version": "7.0.0",
+			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+			"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.12.0"
+			}
+		},
+		"node_modules/is-obj": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+			"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/is-utf8": {
+			"version": "0.2.1",
+			"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+			"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+			"dev": true
+		},
+		"node_modules/isarray": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+			"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+		},
+		"node_modules/json-schema-traverse": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+			"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+		},
+		"node_modules/jsonwebtoken": {
+			"version": "8.5.1",
+			"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+			"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
+			"dependencies": {
+				"jws": "^3.2.2",
+				"lodash.includes": "^4.3.0",
+				"lodash.isboolean": "^3.0.3",
+				"lodash.isinteger": "^4.0.4",
+				"lodash.isnumber": "^3.0.3",
+				"lodash.isplainobject": "^4.0.6",
+				"lodash.isstring": "^4.0.1",
+				"lodash.once": "^4.0.0",
+				"ms": "^2.1.1",
+				"semver": "^5.6.0"
+			},
+			"engines": {
+				"node": ">=4",
+				"npm": ">=1.4.28"
+			}
+		},
+		"node_modules/jwa": {
+			"version": "1.4.1",
+			"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+			"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+			"dependencies": {
+				"buffer-equal-constant-time": "1.0.1",
+				"ecdsa-sig-formatter": "1.0.11",
+				"safe-buffer": "^5.0.1"
+			}
+		},
+		"node_modules/jws": {
+			"version": "3.2.2",
+			"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+			"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+			"dependencies": {
+				"jwa": "^1.4.1",
+				"safe-buffer": "^5.0.1"
+			}
+		},
+		"node_modules/kareem": {
+			"version": "2.3.2",
+			"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz",
+			"integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ=="
+		},
+		"node_modules/lambert-server": {
+			"version": "1.2.8",
+			"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.8.tgz",
+			"integrity": "sha512-vi/Ku/QudY+WIdGO9bc0qLfVhfuJFWXk1+etesPW1vW29sPbmevLL6IwfvCtw+/MyzRAJLOyCBfQ310a68+2QQ==",
+			"dependencies": {
+				"body-parser": "^1.19.0",
+				"chalk": "^4.1.1",
+				"express": "^4.17.1",
+				"express-async-errors": "^3.1.1",
+				"helmet": "^4.4.1",
+				"missing-native-js-functions": "^1.1.8"
+			}
+		},
+		"node_modules/load-json-file": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+			"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+			"dev": true,
+			"dependencies": {
+				"graceful-fs": "^4.1.2",
+				"parse-json": "^2.2.0",
+				"pify": "^2.0.0",
+				"pinkie-promise": "^2.0.0",
+				"strip-bom": "^2.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/lodash.includes": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+			"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
+		},
+		"node_modules/lodash.isboolean": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+			"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
+		},
+		"node_modules/lodash.isinteger": {
+			"version": "4.0.4",
+			"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+			"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
+		},
+		"node_modules/lodash.isnumber": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+			"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
+		},
+		"node_modules/lodash.isplainobject": {
+			"version": "4.0.6",
+			"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+			"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+		},
+		"node_modules/lodash.isstring": {
+			"version": "4.0.1",
+			"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+			"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+		},
+		"node_modules/lodash.once": {
+			"version": "4.1.1",
+			"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+			"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+		},
+		"node_modules/loud-rejection": {
+			"version": "1.6.0",
+			"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+			"integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+			"dev": true,
+			"dependencies": {
+				"currently-unhandled": "^0.4.1",
+				"signal-exit": "^3.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/make-error": {
+			"version": "1.3.6",
+			"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+			"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+			"dev": true
+		},
+		"node_modules/map-obj": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+			"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/media-typer": {
+			"version": "0.3.0",
+			"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+			"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/memory-pager": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
+			"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
+			"optional": true
+		},
+		"node_modules/meow": {
+			"version": "3.7.0",
+			"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+			"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+			"dev": true,
+			"dependencies": {
+				"camelcase-keys": "^2.0.0",
+				"decamelize": "^1.1.2",
+				"loud-rejection": "^1.0.0",
+				"map-obj": "^1.0.1",
+				"minimist": "^1.1.3",
+				"normalize-package-data": "^2.3.4",
+				"object-assign": "^4.0.1",
+				"read-pkg-up": "^1.0.1",
+				"redent": "^1.0.0",
+				"trim-newlines": "^1.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/merge-descriptors": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+			"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+		},
+		"node_modules/methods": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+			"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/mime": {
+			"version": "1.6.0",
+			"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+			"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+			"bin": {
+				"mime": "cli.js"
+			},
+			"engines": {
+				"node": ">=4"
+			}
+		},
+		"node_modules/mime-db": {
+			"version": "1.48.0",
+			"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz",
+			"integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/mime-types": {
+			"version": "2.1.31",
+			"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz",
+			"integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==",
+			"dependencies": {
+				"mime-db": "1.48.0"
+			},
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/minimatch": {
+			"version": "3.0.4",
+			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+			"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+			"dev": true,
+			"dependencies": {
+				"brace-expansion": "^1.1.7"
+			},
+			"engines": {
+				"node": "*"
+			}
+		},
+		"node_modules/minimist": {
+			"version": "1.2.5",
+			"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+			"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+			"dev": true
+		},
+		"node_modules/missing-native-js-functions": {
+			"version": "1.2.7",
+			"resolved": "https://registry.npmjs.org/missing-native-js-functions/-/missing-native-js-functions-1.2.7.tgz",
+			"integrity": "sha512-3JT72wOtgojsdmUaa/LIlEuPmT802Kajnr9RFxSZFCX37oL3epd3mZwSaabqFHxPOUW7nJnix+BAWKwX6O0Q5g=="
+		},
+		"node_modules/mkdirp": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+			"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+			"dev": true,
+			"bin": {
+				"mkdirp": "bin/cmd.js"
+			},
+			"engines": {
+				"node": ">=10"
+			}
+		},
+		"node_modules/mongodb": {
+			"version": "3.6.9",
+			"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.9.tgz",
+			"integrity": "sha512-1nSCKgSunzn/CXwgOWgbPHUWOO5OfERcuOWISmqd610jn0s8BU9K4879iJVabqgpPPbA6hO7rG48eq+fGED3Mg==",
+			"dependencies": {
+				"bl": "^2.2.1",
+				"bson": "^1.1.4",
+				"denque": "^1.4.1",
+				"optional-require": "^1.0.3",
+				"safe-buffer": "^5.1.2"
+			},
+			"engines": {
+				"node": ">=4"
+			},
+			"optionalDependencies": {
+				"saslprep": "^1.0.0"
+			},
+			"peerDependenciesMeta": {
+				"aws4": {
+					"optional": true
+				},
+				"bson-ext": {
+					"optional": true
+				},
+				"kerberos": {
+					"optional": true
+				},
+				"mongodb-client-encryption": {
+					"optional": true
+				},
+				"mongodb-extjson": {
+					"optional": true
+				},
+				"snappy": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/mongoose": {
+			"version": "5.12.12",
+			"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.12.12.tgz",
+			"integrity": "sha512-n+ZmGApaL5x/r92w6S4pb+c075i+YKzg1F9YWkznSzQMtvetj/2dSjj2cqsITpd6z60k3K7ZaosIl6hzHwUA9g==",
+			"dependencies": {
+				"@types/mongodb": "^3.5.27",
+				"bson": "^1.1.4",
+				"kareem": "2.3.2",
+				"mongodb": "3.6.8",
+				"mongoose-legacy-pluralize": "1.0.2",
+				"mpath": "0.8.3",
+				"mquery": "3.2.5",
+				"ms": "2.1.2",
+				"regexp-clone": "1.0.0",
+				"safe-buffer": "5.2.1",
+				"sift": "13.5.2",
+				"sliced": "1.0.1"
+			},
+			"engines": {
+				"node": ">=4.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/mongoose"
+			}
+		},
+		"node_modules/mongoose-autopopulate": {
+			"version": "0.12.3",
+			"resolved": "https://registry.npmjs.org/mongoose-autopopulate/-/mongoose-autopopulate-0.12.3.tgz",
+			"integrity": "sha512-yNmYsfi6OpS/GQ+48mkB0KQ199ExHmmPrt3wt3fyxPHPMtEBGts7yq3wBQR6VgKCPOQaKvCI1URbJCPOtrPeLw==",
+			"peerDependencies": {
+				"mongoose": "4.x || 5.x"
+			}
+		},
+		"node_modules/mongoose-legacy-pluralize": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
+			"integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==",
+			"peerDependencies": {
+				"mongoose": "*"
+			}
+		},
+		"node_modules/mongoose/node_modules/mongodb": {
+			"version": "3.6.8",
+			"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.8.tgz",
+			"integrity": "sha512-sDjJvI73WjON1vapcbyBD3Ao9/VN3TKYY8/QX9EPbs22KaCSrQ5rXo5ZZd44tWJ3wl3FlnrFZ+KyUtNH6+1ZPQ==",
+			"dependencies": {
+				"bl": "^2.2.1",
+				"bson": "^1.1.4",
+				"denque": "^1.4.1",
+				"optional-require": "^1.0.3",
+				"safe-buffer": "^5.1.2"
+			},
+			"engines": {
+				"node": ">=4"
+			},
+			"optionalDependencies": {
+				"saslprep": "^1.0.0"
+			},
+			"peerDependenciesMeta": {
+				"aws4": {
+					"optional": true
+				},
+				"bson-ext": {
+					"optional": true
+				},
+				"kerberos": {
+					"optional": true
+				},
+				"mongodb-client-encryption": {
+					"optional": true
+				},
+				"mongodb-extjson": {
+					"optional": true
+				},
+				"snappy": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/mongoose/node_modules/ms": {
+			"version": "2.1.2",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+			"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+		},
+		"node_modules/mpath": {
+			"version": "0.8.3",
+			"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz",
+			"integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==",
+			"engines": {
+				"node": ">=4.0.0"
+			}
+		},
+		"node_modules/mquery": {
+			"version": "3.2.5",
+			"resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz",
+			"integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==",
+			"dependencies": {
+				"bluebird": "3.5.1",
+				"debug": "3.1.0",
+				"regexp-clone": "^1.0.0",
+				"safe-buffer": "5.1.2",
+				"sliced": "1.0.1"
+			},
+			"engines": {
+				"node": ">=4.0.0"
+			}
+		},
+		"node_modules/mquery/node_modules/debug": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+			"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+			"dependencies": {
+				"ms": "2.0.0"
+			}
+		},
+		"node_modules/mquery/node_modules/ms": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+			"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+		},
+		"node_modules/mquery/node_modules/safe-buffer": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+		},
+		"node_modules/ms": {
+			"version": "2.1.3",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+			"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+		},
+		"node_modules/nan": {
+			"version": "2.14.2",
+			"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
+			"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
+			"dev": true
+		},
+		"node_modules/negotiator": {
+			"version": "0.6.2",
+			"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+			"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/node-fetch": {
+			"version": "2.6.1",
+			"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
+			"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
+			"engines": {
+				"node": "4.x || >=6.0.0"
+			}
+		},
+		"node_modules/normalize-package-data": {
+			"version": "2.5.0",
+			"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+			"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+			"dev": true,
+			"dependencies": {
+				"hosted-git-info": "^2.1.4",
+				"resolve": "^1.10.0",
+				"semver": "2 || 3 || 4 || 5",
+				"validate-npm-package-license": "^3.0.1"
+			}
+		},
+		"node_modules/normalize-path": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+			"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/object-assign": {
+			"version": "4.1.1",
+			"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+			"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/on-finished": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+			"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+			"dependencies": {
+				"ee-first": "1.1.1"
+			},
+			"engines": {
+				"node": ">= 0.8"
+			}
+		},
+		"node_modules/once": {
+			"version": "1.4.0",
+			"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+			"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+			"dev": true,
+			"dependencies": {
+				"wrappy": "1"
+			}
+		},
+		"node_modules/optional-require": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
+			"integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==",
+			"engines": {
+				"node": ">=4"
+			}
+		},
+		"node_modules/parse-json": {
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+			"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+			"dev": true,
+			"dependencies": {
+				"error-ex": "^1.2.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/parseurl": {
+			"version": "1.3.3",
+			"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+			"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+			"engines": {
+				"node": ">= 0.8"
+			}
+		},
+		"node_modules/path-exists": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+			"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+			"dev": true,
+			"dependencies": {
+				"pinkie-promise": "^2.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/path-is-absolute": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/path-parse": {
+			"version": "1.0.7",
+			"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+			"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+			"dev": true
+		},
+		"node_modules/path-to-regexp": {
+			"version": "0.1.7",
+			"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+			"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+		},
+		"node_modules/path-type": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+			"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+			"dev": true,
+			"dependencies": {
+				"graceful-fs": "^4.1.2",
+				"pify": "^2.0.0",
+				"pinkie-promise": "^2.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/picomatch": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+			"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
+			"dev": true,
+			"engines": {
+				"node": ">=8.6"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/jonschlinkert"
+			}
+		},
+		"node_modules/pify": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+			"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/pinkie": {
+			"version": "2.0.4",
+			"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+			"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/pinkie-promise": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+			"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+			"dev": true,
+			"dependencies": {
+				"pinkie": "^2.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/process-nextick-args": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+			"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+		},
+		"node_modules/proxy-addr": {
+			"version": "2.0.7",
+			"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+			"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+			"dependencies": {
+				"forwarded": "0.2.0",
+				"ipaddr.js": "1.9.1"
+			},
+			"engines": {
+				"node": ">= 0.10"
+			}
+		},
+		"node_modules/punycode": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+			"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+			"engines": {
+				"node": ">=6"
+			}
+		},
+		"node_modules/qs": {
+			"version": "6.7.0",
+			"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+			"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+			"engines": {
+				"node": ">=0.6"
+			}
+		},
+		"node_modules/querystringify": {
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+			"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
+		},
+		"node_modules/range-parser": {
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+			"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/raw-body": {
+			"version": "2.4.0",
+			"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+			"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+			"dependencies": {
+				"bytes": "3.1.0",
+				"http-errors": "1.7.2",
+				"iconv-lite": "0.4.24",
+				"unpipe": "1.0.0"
+			},
+			"engines": {
+				"node": ">= 0.8"
+			}
+		},
+		"node_modules/read-pkg": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+			"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+			"dev": true,
+			"dependencies": {
+				"load-json-file": "^1.0.0",
+				"normalize-package-data": "^2.3.2",
+				"path-type": "^1.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/read-pkg-up": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+			"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+			"dev": true,
+			"dependencies": {
+				"find-up": "^1.0.0",
+				"read-pkg": "^1.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/readable-stream": {
+			"version": "2.3.7",
+			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+			"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+			"dependencies": {
+				"core-util-is": "~1.0.0",
+				"inherits": "~2.0.3",
+				"isarray": "~1.0.0",
+				"process-nextick-args": "~2.0.0",
+				"safe-buffer": "~5.1.1",
+				"string_decoder": "~1.1.1",
+				"util-deprecate": "~1.0.1"
+			}
+		},
+		"node_modules/readable-stream/node_modules/safe-buffer": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+		},
+		"node_modules/readdirp": {
+			"version": "3.5.0",
+			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
+			"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
+			"dev": true,
+			"dependencies": {
+				"picomatch": "^2.2.1"
+			},
+			"engines": {
+				"node": ">=8.10.0"
+			}
+		},
+		"node_modules/redent": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+			"integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+			"dev": true,
+			"dependencies": {
+				"indent-string": "^2.1.0",
+				"strip-indent": "^1.0.1"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/regexp-clone": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
+			"integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw=="
+		},
+		"node_modules/repeating": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+			"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+			"dev": true,
+			"dependencies": {
+				"is-finite": "^1.0.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/require-from-string": {
+			"version": "2.0.2",
+			"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+			"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/requires-port": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+			"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
+		},
+		"node_modules/resolve": {
+			"version": "1.20.0",
+			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+			"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+			"dev": true,
+			"dependencies": {
+				"is-core-module": "^2.2.0",
+				"path-parse": "^1.0.6"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/ljharb"
+			}
+		},
+		"node_modules/rimraf": {
+			"version": "2.7.1",
+			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+			"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+			"dev": true,
+			"dependencies": {
+				"glob": "^7.1.3"
+			},
+			"bin": {
+				"rimraf": "bin.js"
+			}
+		},
+		"node_modules/safe-buffer": {
+			"version": "5.2.1",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+			"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+			"funding": [
+				{
+					"type": "github",
+					"url": "https://github.com/sponsors/feross"
+				},
+				{
+					"type": "patreon",
+					"url": "https://www.patreon.com/feross"
+				},
+				{
+					"type": "consulting",
+					"url": "https://feross.org/support"
+				}
+			]
+		},
+		"node_modules/safer-buffer": {
+			"version": "2.1.2",
+			"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+			"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+		},
+		"node_modules/saslprep": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
+			"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
+			"optional": true,
+			"dependencies": {
+				"sparse-bitfield": "^3.0.3"
+			},
+			"engines": {
+				"node": ">=6"
+			}
+		},
+		"node_modules/semver": {
+			"version": "5.7.1",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+			"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+			"bin": {
+				"semver": "bin/semver"
+			}
+		},
+		"node_modules/send": {
+			"version": "0.17.1",
+			"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+			"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+			"dependencies": {
+				"debug": "2.6.9",
+				"depd": "~1.1.2",
+				"destroy": "~1.0.4",
+				"encodeurl": "~1.0.2",
+				"escape-html": "~1.0.3",
+				"etag": "~1.8.1",
+				"fresh": "0.5.2",
+				"http-errors": "~1.7.2",
+				"mime": "1.6.0",
+				"ms": "2.1.1",
+				"on-finished": "~2.3.0",
+				"range-parser": "~1.2.1",
+				"statuses": "~1.5.0"
+			},
+			"engines": {
+				"node": ">= 0.8.0"
+			}
+		},
+		"node_modules/send/node_modules/ms": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+			"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+		},
+		"node_modules/serve-static": {
+			"version": "1.14.1",
+			"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+			"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+			"dependencies": {
+				"encodeurl": "~1.0.2",
+				"escape-html": "~1.0.3",
+				"parseurl": "~1.3.3",
+				"send": "0.17.1"
+			},
+			"engines": {
+				"node": ">= 0.8.0"
+			}
+		},
+		"node_modules/setprototypeof": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+			"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+		},
+		"node_modules/sift": {
+			"version": "13.5.2",
+			"resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz",
+			"integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA=="
+		},
+		"node_modules/signal-exit": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+			"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+			"dev": true
+		},
+		"node_modules/sliced": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
+			"integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
+		},
+		"node_modules/source-map": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+			"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/source-map-support": {
+			"version": "0.5.19",
+			"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+			"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+			"dev": true,
+			"dependencies": {
+				"buffer-from": "^1.0.0",
+				"source-map": "^0.6.0"
+			}
+		},
+		"node_modules/sparse-bitfield": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
+			"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
+			"optional": true,
+			"dependencies": {
+				"memory-pager": "^1.0.2"
+			}
+		},
+		"node_modules/spdx-correct": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+			"integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+			"dev": true,
+			"dependencies": {
+				"spdx-expression-parse": "^3.0.0",
+				"spdx-license-ids": "^3.0.0"
+			}
+		},
+		"node_modules/spdx-exceptions": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+			"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+			"dev": true
+		},
+		"node_modules/spdx-expression-parse": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+			"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+			"dev": true,
+			"dependencies": {
+				"spdx-exceptions": "^2.1.0",
+				"spdx-license-ids": "^3.0.0"
+			}
+		},
+		"node_modules/spdx-license-ids": {
+			"version": "3.0.9",
+			"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz",
+			"integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==",
+			"dev": true
+		},
+		"node_modules/statuses": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+			"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/string_decoder": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+			"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+			"dependencies": {
+				"safe-buffer": "~5.1.0"
+			}
+		},
+		"node_modules/string_decoder/node_modules/safe-buffer": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+		},
+		"node_modules/strip-bom": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+			"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+			"dev": true,
+			"dependencies": {
+				"is-utf8": "^0.2.0"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/strip-indent": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+			"integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+			"dev": true,
+			"dependencies": {
+				"get-stdin": "^4.0.1"
+			},
+			"bin": {
+				"strip-indent": "cli.js"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/strip-json-comments": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+			"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/supports-color": {
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+			"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+			"dependencies": {
+				"has-flag": "^4.0.0"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/to-regex-range": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+			"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+			"dev": true,
+			"dependencies": {
+				"is-number": "^7.0.0"
+			},
+			"engines": {
+				"node": ">=8.0"
+			}
+		},
+		"node_modules/toidentifier": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+			"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+			"engines": {
+				"node": ">=0.6"
+			}
+		},
+		"node_modules/tree-kill": {
+			"version": "1.2.2",
+			"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+			"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+			"dev": true,
+			"bin": {
+				"tree-kill": "cli.js"
+			}
+		},
+		"node_modules/trim-newlines": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+			"integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/ts-node": {
+			"version": "9.1.1",
+			"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz",
+			"integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==",
+			"dev": true,
+			"dependencies": {
+				"arg": "^4.1.0",
+				"create-require": "^1.1.0",
+				"diff": "^4.0.1",
+				"make-error": "^1.1.1",
+				"source-map-support": "^0.5.17",
+				"yn": "3.1.1"
+			},
+			"bin": {
+				"ts-node": "dist/bin.js",
+				"ts-node-script": "dist/bin-script.js",
+				"ts-node-transpile-only": "dist/bin-transpile.js",
+				"ts-script": "dist/bin-script-deprecated.js"
+			},
+			"engines": {
+				"node": ">=10.0.0"
+			},
+			"peerDependencies": {
+				"typescript": ">=2.7"
+			}
+		},
+		"node_modules/ts-node-dev": {
+			"version": "1.1.6",
+			"resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.1.6.tgz",
+			"integrity": "sha512-RTUi7mHMNQospArGz07KiraQcdgUVNXKsgO2HAi7FoiyPMdTDqdniB6K1dqyaIxT7c9v/VpSbfBZPS6uVpaFLQ==",
+			"dev": true,
+			"dependencies": {
+				"chokidar": "^3.5.1",
+				"dateformat": "~1.0.4-1.2.3",
+				"dynamic-dedupe": "^0.3.0",
+				"minimist": "^1.2.5",
+				"mkdirp": "^1.0.4",
+				"resolve": "^1.0.0",
+				"rimraf": "^2.6.1",
+				"source-map-support": "^0.5.12",
+				"tree-kill": "^1.2.2",
+				"ts-node": "^9.0.0",
+				"tsconfig": "^7.0.0"
+			},
+			"bin": {
+				"ts-node-dev": "lib/bin.js",
+				"tsnd": "lib/bin.js"
+			},
+			"engines": {
+				"node": ">=0.8.0"
+			},
+			"peerDependencies": {
+				"node-notifier": "*",
+				"typescript": "*"
+			},
+			"peerDependenciesMeta": {
+				"node-notifier": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/tsconfig": {
+			"version": "7.0.0",
+			"resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
+			"integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
+			"dev": true,
+			"dependencies": {
+				"@types/strip-bom": "^3.0.0",
+				"@types/strip-json-comments": "0.0.30",
+				"strip-bom": "^3.0.0",
+				"strip-json-comments": "^2.0.0"
+			}
+		},
+		"node_modules/tsconfig/node_modules/strip-bom": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+			"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+			"dev": true,
+			"engines": {
+				"node": ">=4"
+			}
+		},
+		"node_modules/type-is": {
+			"version": "1.6.18",
+			"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+			"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+			"dependencies": {
+				"media-typer": "0.3.0",
+				"mime-types": "~2.1.24"
+			},
+			"engines": {
+				"node": ">= 0.6"
+			}
+		},
+		"node_modules/typescript": {
+			"version": "4.3.2",
+			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
+			"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==",
+			"bin": {
+				"tsc": "bin/tsc",
+				"tsserver": "bin/tsserver"
+			},
+			"engines": {
+				"node": ">=4.2.0"
+			}
+		},
+		"node_modules/unpipe": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+			"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+			"engines": {
+				"node": ">= 0.8"
+			}
+		},
+		"node_modules/uri-js": {
+			"version": "4.4.1",
+			"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+			"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+			"dependencies": {
+				"punycode": "^2.1.0"
+			}
+		},
+		"node_modules/url-parse": {
+			"version": "1.5.3",
+			"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
+			"integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
+			"dependencies": {
+				"querystringify": "^2.1.1",
+				"requires-port": "^1.0.0"
+			}
+		},
+		"node_modules/util-deprecate": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+			"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+		},
+		"node_modules/utils-merge": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+			"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+			"engines": {
+				"node": ">= 0.4.0"
+			}
+		},
+		"node_modules/uuid": {
+			"version": "8.3.2",
+			"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+			"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+			"bin": {
+				"uuid": "dist/bin/uuid"
+			}
+		},
+		"node_modules/validate-npm-package-license": {
+			"version": "3.0.4",
+			"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+			"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+			"dev": true,
+			"dependencies": {
+				"spdx-correct": "^3.0.0",
+				"spdx-expression-parse": "^3.0.0"
+			}
+		},
+		"node_modules/vary": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+			"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+			"engines": {
+				"node": ">= 0.8"
+			}
+		},
+		"node_modules/wrappy": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+			"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+			"dev": true
+		},
+		"node_modules/ws": {
+			"version": "7.4.6",
+			"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+			"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
+			"engines": {
+				"node": ">=8.3.0"
+			},
+			"peerDependencies": {
+				"bufferutil": "^4.0.1",
+				"utf-8-validate": "^5.0.2"
+			},
+			"peerDependenciesMeta": {
+				"bufferutil": {
+					"optional": true
+				},
+				"utf-8-validate": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/xtend": {
+			"version": "4.0.2",
+			"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+			"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.4"
+			}
+		},
+		"node_modules/yn": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+			"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+			"dev": true,
+			"engines": {
+				"node": ">=6"
+			}
+		}
+	},
+	"dependencies": {
+		"@fosscord/server-util": {
+			"version": "1.3.51",
+			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.51.tgz",
+			"integrity": "sha512-z7gAwj8UFTrbabtyMqb/7mhiTTpk07dKMu2ZaL4yeTPBR2Ppnkd3JqYHcrqIyMfeENgzTFoOVSjtun1aFUFDag==",
+			"requires": {
+				"@types/jsonwebtoken": "^8.5.0",
+				"@types/mongoose-autopopulate": "^0.10.1",
+				"@types/mongoose-lean-virtuals": "^0.5.1",
+				"@types/node": "^14.14.25",
+				"ajv": "^8.5.0",
+				"amqplib": "^0.8.0",
+				"dot-prop": "^6.0.1",
+				"env-paths": "^2.2.1",
+				"jsonwebtoken": "^8.5.1",
+				"missing-native-js-functions": "^1.2.2",
+				"mongodb": "^3.6.9",
+				"mongoose": "^5.12.3",
+				"mongoose-autopopulate": "^0.12.3",
+				"typescript": "^4.1.3"
+			}
+		},
+		"@types/amqplib": {
+			"version": "0.8.1",
+			"resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.8.1.tgz",
+			"integrity": "sha512-8dCjF+dHZ8Y6JOoHD1BMnxP0quAncvZq4wA/lS072NjX9vIzVRSMcmfKy2Os8ZQ8VWWp74MD09GMbVbKS6/Fxw==",
+			"dev": true,
+			"requires": {
+				"@types/bluebird": "*",
+				"@types/node": "*"
+			}
+		},
+		"@types/bluebird": {
+			"version": "3.5.36",
+			"resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz",
+			"integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==",
+			"dev": true
+		},
+		"@types/bson": {
+			"version": "4.0.3",
+			"resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz",
+			"integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==",
+			"requires": {
+				"@types/node": "*"
+			}
+		},
+		"@types/jsonwebtoken": {
+			"version": "8.5.1",
+			"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+			"integrity": "sha512-rNAPdomlIUX0i0cg2+I+Q1wOUr531zHBQ+cV/28PJ39bSPKjahatZZ2LMuhiguETkCgLVzfruw/ZvNMNkKoSzw==",
+			"requires": {
+				"@types/node": "*"
+			}
+		},
+		"@types/mongodb": {
+			"version": "3.6.17",
+			"resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.17.tgz",
+			"integrity": "sha512-9hhgvYPdC5iHyyksPcKCu45gfaAIPQHKHGdvNXu4582DmOZX3wrUJIJPT40o4G1oTKPgpMMFqZglOTjhnYoF+A==",
+			"requires": {
+				"@types/bson": "*",
+				"@types/node": "*"
+			}
+		},
+		"@types/mongoose": {
+			"version": "5.10.5",
+			"resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.10.5.tgz",
+			"integrity": "sha512-37QMIA954T3n+HSksSNLlxZsqF8fMJu5S4dyPBod6gRxGtsXlQ9jUtL8BE8Seimv99u79eLXI3bggoCnSQ/fxQ==",
+			"requires": {
+				"@types/mongodb": "*",
+				"@types/node": "*"
+			}
+		},
+		"@types/mongoose-autopopulate": {
+			"version": "0.10.1",
+			"resolved": "https://registry.npmjs.org/@types/mongoose-autopopulate/-/mongoose-autopopulate-0.10.1.tgz",
+			"integrity": "sha512-L67MAIE3WEoTtt7a7/spRYk+76lgp67FAP6I38Y9NcC1kQuzwqnukTaJzodfb8180wxHZM4qt68u6x6ptuDRaQ==",
+			"requires": {
+				"@types/mongoose": "*"
+			}
+		},
+		"@types/mongoose-lean-virtuals": {
+			"version": "0.5.1",
+			"resolved": "https://registry.npmjs.org/@types/mongoose-lean-virtuals/-/mongoose-lean-virtuals-0.5.1.tgz",
+			"integrity": "sha512-bNk+QLjP5VZU4EsJag4xQsjLAa8CEm/SKZDyiC2kM208wIrGum6daD7j45Oqs50bWNGfqZYRuEhh8xZ17D7aEw==",
+			"requires": {
+				"@types/mongoose": "*"
+			}
+		},
+		"@types/node": {
+			"version": "14.17.1",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.1.tgz",
+			"integrity": "sha512-/tpUyFD7meeooTRwl3sYlihx2BrJE7q9XF71EguPFIySj9B7qgnRtHsHTho+0AUm4m1SvWGm6uSncrR94q6Vtw=="
+		},
+		"@types/strip-bom": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
+			"integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
+			"dev": true
+		},
+		"@types/strip-json-comments": {
+			"version": "0.0.30",
+			"resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
+			"integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
+			"dev": true
+		},
+		"@types/uuid": {
+			"version": "8.3.0",
+			"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz",
+			"integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==",
+			"dev": true
+		},
+		"@types/ws": {
+			"version": "7.4.4",
+			"resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.4.tgz",
+			"integrity": "sha512-d/7W23JAXPodQNbOZNXvl2K+bqAQrCMwlh/nuQsPSQk6Fq0opHoPrUw43aHsvSbIiQPr8Of2hkFbnz1XBFVyZQ==",
+			"dev": true,
+			"requires": {
+				"@types/node": "*"
+			}
+		},
+		"accepts": {
+			"version": "1.3.7",
+			"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+			"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+			"requires": {
+				"mime-types": "~2.1.24",
+				"negotiator": "0.6.2"
+			}
+		},
+		"ajv": {
+			"version": "8.5.0",
+			"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz",
+			"integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==",
+			"requires": {
+				"fast-deep-equal": "^3.1.1",
+				"json-schema-traverse": "^1.0.0",
+				"require-from-string": "^2.0.2",
+				"uri-js": "^4.2.2"
+			}
+		},
+		"amqplib": {
+			"version": "0.8.0",
+			"resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.8.0.tgz",
+			"integrity": "sha512-icU+a4kkq4Y1PS4NNi+YPDMwdlbFcZ1EZTQT2nigW3fvOb6AOgUQ9+Mk4ue0Zu5cBg/XpDzB40oH10ysrk2dmA==",
+			"requires": {
+				"bitsyntax": "~0.1.0",
+				"bluebird": "^3.7.2",
+				"buffer-more-ints": "~1.0.0",
+				"readable-stream": "1.x >=1.1.9",
+				"safe-buffer": "~5.2.1",
+				"url-parse": "~1.5.1"
+			},
+			"dependencies": {
+				"bluebird": {
+					"version": "3.7.2",
+					"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+					"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+				},
+				"isarray": {
+					"version": "0.0.1",
+					"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+					"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+				},
+				"readable-stream": {
+					"version": "1.1.14",
+					"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+					"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+					"requires": {
+						"core-util-is": "~1.0.0",
+						"inherits": "~2.0.1",
+						"isarray": "0.0.1",
+						"string_decoder": "~0.10.x"
+					}
+				},
+				"string_decoder": {
+					"version": "0.10.31",
+					"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+					"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+				}
+			}
+		},
+		"ansi-styles": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+			"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+			"requires": {
+				"color-convert": "^2.0.1"
+			}
+		},
+		"anymatch": {
+			"version": "3.1.2",
+			"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+			"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+			"dev": true,
+			"requires": {
+				"normalize-path": "^3.0.0",
+				"picomatch": "^2.0.4"
+			}
+		},
+		"arg": {
+			"version": "4.1.3",
+			"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+			"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+			"dev": true
+		},
+		"array-find-index": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+			"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+			"dev": true
+		},
+		"array-flatten": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+			"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+		},
+		"balanced-match": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+			"dev": true
+		},
+		"binary-extensions": {
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+			"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+			"dev": true
+		},
+		"bindings": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+			"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+			"dev": true,
+			"requires": {
+				"file-uri-to-path": "1.0.0"
+			}
+		},
+		"bitsyntax": {
+			"version": "0.1.0",
+			"resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz",
+			"integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==",
+			"requires": {
+				"buffer-more-ints": "~1.0.0",
+				"debug": "~2.6.9",
+				"safe-buffer": "~5.1.2"
+			},
+			"dependencies": {
+				"safe-buffer": {
+					"version": "5.1.2",
+					"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+					"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+				}
+			}
+		},
+		"bl": {
+			"version": "2.2.1",
+			"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
+			"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
+			"requires": {
+				"readable-stream": "^2.3.5",
+				"safe-buffer": "^5.1.1"
+			}
+		},
+		"bluebird": {
+			"version": "3.5.1",
+			"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
+			"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
+		},
+		"body-parser": {
+			"version": "1.19.0",
+			"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+			"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+			"requires": {
+				"bytes": "3.1.0",
+				"content-type": "~1.0.4",
+				"debug": "2.6.9",
+				"depd": "~1.1.2",
+				"http-errors": "1.7.2",
+				"iconv-lite": "0.4.24",
+				"on-finished": "~2.3.0",
+				"qs": "6.7.0",
+				"raw-body": "2.4.0",
+				"type-is": "~1.6.17"
+			}
+		},
+		"brace-expansion": {
+			"version": "1.1.11",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+			"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+			"dev": true,
+			"requires": {
+				"balanced-match": "^1.0.0",
+				"concat-map": "0.0.1"
+			}
+		},
+		"braces": {
+			"version": "3.0.2",
+			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+			"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+			"dev": true,
+			"requires": {
+				"fill-range": "^7.0.1"
+			}
+		},
+		"bson": {
+			"version": "1.1.6",
+			"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
+			"integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg=="
+		},
+		"buffer-equal-constant-time": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+			"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+		},
+		"buffer-from": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+			"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+			"dev": true
+		},
+		"buffer-more-ints": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
+			"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
+		},
+		"bytes": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+			"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+		},
+		"camelcase": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+			"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+			"dev": true
+		},
+		"camelcase-keys": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+			"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+			"dev": true,
+			"requires": {
+				"camelcase": "^2.0.0",
+				"map-obj": "^1.0.0"
+			}
+		},
+		"chalk": {
+			"version": "4.1.1",
+			"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
+			"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
+			"requires": {
+				"ansi-styles": "^4.1.0",
+				"supports-color": "^7.1.0"
+			}
+		},
+		"chokidar": {
+			"version": "3.5.1",
+			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
+			"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
+			"dev": true,
+			"requires": {
+				"anymatch": "~3.1.1",
+				"braces": "~3.0.2",
+				"fsevents": "~2.3.1",
+				"glob-parent": "~5.1.0",
+				"is-binary-path": "~2.1.0",
+				"is-glob": "~4.0.1",
+				"normalize-path": "~3.0.0",
+				"readdirp": "~3.5.0"
+			}
+		},
+		"color-convert": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+			"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+			"requires": {
+				"color-name": "~1.1.4"
+			}
+		},
+		"color-name": {
+			"version": "1.1.4",
+			"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+			"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+		},
+		"concat-map": {
+			"version": "0.0.1",
+			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+			"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+			"dev": true
+		},
+		"content-disposition": {
+			"version": "0.5.3",
+			"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+			"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+			"requires": {
+				"safe-buffer": "5.1.2"
+			},
+			"dependencies": {
+				"safe-buffer": {
+					"version": "5.1.2",
+					"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+					"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+				}
+			}
+		},
+		"content-type": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+			"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+		},
+		"cookie": {
+			"version": "0.4.0",
+			"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+			"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
+		},
+		"cookie-signature": {
+			"version": "1.0.6",
+			"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+			"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+		},
+		"core-util-is": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+			"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+		},
+		"create-require": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+			"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
+			"dev": true
+		},
+		"currently-unhandled": {
+			"version": "0.4.1",
+			"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+			"integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+			"dev": true,
+			"requires": {
+				"array-find-index": "^1.0.1"
+			}
+		},
+		"dateformat": {
+			"version": "1.0.12",
+			"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+			"integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+			"dev": true,
+			"requires": {
+				"get-stdin": "^4.0.1",
+				"meow": "^3.3.0"
+			}
+		},
+		"debug": {
+			"version": "2.6.9",
+			"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+			"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+			"requires": {
+				"ms": "2.0.0"
+			},
+			"dependencies": {
+				"ms": {
+					"version": "2.0.0",
+					"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+					"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+				}
+			}
+		},
+		"decamelize": {
+			"version": "1.2.0",
+			"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+			"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+			"dev": true
+		},
+		"denque": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
+			"integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ=="
+		},
+		"depd": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+			"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+		},
+		"destroy": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+			"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+		},
+		"diff": {
+			"version": "4.0.2",
+			"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+			"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+			"dev": true
+		},
+		"dot-prop": {
+			"version": "6.0.1",
+			"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
+			"integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
+			"requires": {
+				"is-obj": "^2.0.0"
+			}
+		},
+		"dotenv": {
+			"version": "8.6.0",
+			"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
+			"integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g=="
+		},
+		"dynamic-dedupe": {
+			"version": "0.3.0",
+			"resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
+			"integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
+			"dev": true,
+			"requires": {
+				"xtend": "^4.0.0"
+			}
+		},
+		"ecdsa-sig-formatter": {
+			"version": "1.0.11",
+			"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+			"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+			"requires": {
+				"safe-buffer": "^5.0.1"
+			}
+		},
+		"ee-first": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+			"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+		},
+		"encodeurl": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+			"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+		},
+		"env-paths": {
+			"version": "2.2.1",
+			"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+			"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="
+		},
+		"erlpack": {
+			"version": "0.1.3",
+			"resolved": "https://registry.npmjs.org/erlpack/-/erlpack-0.1.3.tgz",
+			"integrity": "sha512-QeG9v8CVsY/a/IoQi8zjn23aYKcziOihAxwjUl3tI/KB4R1FjTtctDAAMovgtpC16S+WiOauers2oWwIOQtKBQ==",
+			"dev": true,
+			"requires": {
+				"bindings": "^1.5.0",
+				"nan": "^2.14.0"
+			}
+		},
+		"error-ex": {
+			"version": "1.3.2",
+			"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+			"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+			"dev": true,
+			"requires": {
+				"is-arrayish": "^0.2.1"
+			}
+		},
+		"escape-html": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+			"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+		},
+		"etag": {
+			"version": "1.8.1",
+			"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+			"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+		},
+		"express": {
+			"version": "4.17.1",
+			"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+			"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+			"requires": {
+				"accepts": "~1.3.7",
+				"array-flatten": "1.1.1",
+				"body-parser": "1.19.0",
+				"content-disposition": "0.5.3",
+				"content-type": "~1.0.4",
+				"cookie": "0.4.0",
+				"cookie-signature": "1.0.6",
+				"debug": "2.6.9",
+				"depd": "~1.1.2",
+				"encodeurl": "~1.0.2",
+				"escape-html": "~1.0.3",
+				"etag": "~1.8.1",
+				"finalhandler": "~1.1.2",
+				"fresh": "0.5.2",
+				"merge-descriptors": "1.0.1",
+				"methods": "~1.1.2",
+				"on-finished": "~2.3.0",
+				"parseurl": "~1.3.3",
+				"path-to-regexp": "0.1.7",
+				"proxy-addr": "~2.0.5",
+				"qs": "6.7.0",
+				"range-parser": "~1.2.1",
+				"safe-buffer": "5.1.2",
+				"send": "0.17.1",
+				"serve-static": "1.14.1",
+				"setprototypeof": "1.1.1",
+				"statuses": "~1.5.0",
+				"type-is": "~1.6.18",
+				"utils-merge": "1.0.1",
+				"vary": "~1.1.2"
+			},
+			"dependencies": {
+				"safe-buffer": {
+					"version": "5.1.2",
+					"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+					"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+				}
+			}
+		},
+		"express-async-errors": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz",
+			"integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==",
+			"requires": {}
+		},
+		"fast-deep-equal": {
+			"version": "3.1.3",
+			"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+		},
+		"file-uri-to-path": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+			"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+			"dev": true
+		},
+		"fill-range": {
+			"version": "7.0.1",
+			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+			"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+			"dev": true,
+			"requires": {
+				"to-regex-range": "^5.0.1"
+			}
+		},
+		"finalhandler": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+			"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+			"requires": {
+				"debug": "2.6.9",
+				"encodeurl": "~1.0.2",
+				"escape-html": "~1.0.3",
+				"on-finished": "~2.3.0",
+				"parseurl": "~1.3.3",
+				"statuses": "~1.5.0",
+				"unpipe": "~1.0.0"
+			}
+		},
+		"find-up": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+			"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+			"dev": true,
+			"requires": {
+				"path-exists": "^2.0.0",
+				"pinkie-promise": "^2.0.0"
+			}
+		},
+		"forwarded": {
+			"version": "0.2.0",
+			"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+			"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
+		},
+		"fresh": {
+			"version": "0.5.2",
+			"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+			"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+		},
+		"fs.realpath": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+			"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+			"dev": true
+		},
+		"fsevents": {
+			"version": "2.3.2",
+			"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+			"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+			"dev": true,
+			"optional": true
+		},
+		"function-bind": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+			"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+			"dev": true
+		},
+		"get-stdin": {
+			"version": "4.0.1",
+			"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+			"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+			"dev": true
+		},
+		"glob": {
+			"version": "7.1.7",
+			"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+			"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+			"dev": true,
+			"requires": {
+				"fs.realpath": "^1.0.0",
+				"inflight": "^1.0.4",
+				"inherits": "2",
+				"minimatch": "^3.0.4",
+				"once": "^1.3.0",
+				"path-is-absolute": "^1.0.0"
+			}
+		},
+		"glob-parent": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+			"dev": true,
+			"requires": {
+				"is-glob": "^4.0.1"
+			}
+		},
+		"graceful-fs": {
+			"version": "4.2.6",
+			"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
+			"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
+			"dev": true
+		},
+		"has": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+			"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+			"dev": true,
+			"requires": {
+				"function-bind": "^1.1.1"
+			}
+		},
+		"has-flag": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+			"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+		},
+		"helmet": {
+			"version": "4.6.0",
+			"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz",
+			"integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg=="
+		},
+		"hosted-git-info": {
+			"version": "2.8.9",
+			"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+			"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+			"dev": true
+		},
+		"http-errors": {
+			"version": "1.7.2",
+			"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+			"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+			"requires": {
+				"depd": "~1.1.2",
+				"inherits": "2.0.3",
+				"setprototypeof": "1.1.1",
+				"statuses": ">= 1.5.0 < 2",
+				"toidentifier": "1.0.0"
+			}
+		},
+		"iconv-lite": {
+			"version": "0.4.24",
+			"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+			"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+			"requires": {
+				"safer-buffer": ">= 2.1.2 < 3"
+			}
+		},
+		"indent-string": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+			"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+			"dev": true,
+			"requires": {
+				"repeating": "^2.0.0"
+			}
+		},
+		"inflight": {
+			"version": "1.0.6",
+			"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+			"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+			"dev": true,
+			"requires": {
+				"once": "^1.3.0",
+				"wrappy": "1"
+			}
+		},
+		"inherits": {
+			"version": "2.0.3",
+			"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+			"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+		},
+		"ipaddr.js": {
+			"version": "1.9.1",
+			"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+			"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
+		},
+		"is-arrayish": {
+			"version": "0.2.1",
+			"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+			"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+			"dev": true
+		},
+		"is-binary-path": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+			"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+			"dev": true,
+			"requires": {
+				"binary-extensions": "^2.0.0"
+			}
+		},
+		"is-core-module": {
+			"version": "2.4.0",
+			"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
+			"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
+			"dev": true,
+			"requires": {
+				"has": "^1.0.3"
+			}
+		},
+		"is-extglob": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+			"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+			"dev": true
+		},
+		"is-finite": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
+			"integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
+			"dev": true
+		},
+		"is-glob": {
+			"version": "4.0.1",
+			"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+			"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+			"dev": true,
+			"requires": {
+				"is-extglob": "^2.1.1"
+			}
+		},
+		"is-number": {
+			"version": "7.0.0",
+			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+			"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+			"dev": true
+		},
+		"is-obj": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+			"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
+		},
+		"is-utf8": {
+			"version": "0.2.1",
+			"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+			"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+			"dev": true
+		},
+		"isarray": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+			"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+		},
+		"json-schema-traverse": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+			"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+		},
+		"jsonwebtoken": {
+			"version": "8.5.1",
+			"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+			"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
+			"requires": {
+				"jws": "^3.2.2",
+				"lodash.includes": "^4.3.0",
+				"lodash.isboolean": "^3.0.3",
+				"lodash.isinteger": "^4.0.4",
+				"lodash.isnumber": "^3.0.3",
+				"lodash.isplainobject": "^4.0.6",
+				"lodash.isstring": "^4.0.1",
+				"lodash.once": "^4.0.0",
+				"ms": "^2.1.1",
+				"semver": "^5.6.0"
+			}
+		},
+		"jwa": {
+			"version": "1.4.1",
+			"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+			"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+			"requires": {
+				"buffer-equal-constant-time": "1.0.1",
+				"ecdsa-sig-formatter": "1.0.11",
+				"safe-buffer": "^5.0.1"
+			}
+		},
+		"jws": {
+			"version": "3.2.2",
+			"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+			"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+			"requires": {
+				"jwa": "^1.4.1",
+				"safe-buffer": "^5.0.1"
+			}
+		},
+		"kareem": {
+			"version": "2.3.2",
+			"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz",
+			"integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ=="
+		},
+		"lambert-server": {
+			"version": "1.2.8",
+			"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.8.tgz",
+			"integrity": "sha512-vi/Ku/QudY+WIdGO9bc0qLfVhfuJFWXk1+etesPW1vW29sPbmevLL6IwfvCtw+/MyzRAJLOyCBfQ310a68+2QQ==",
+			"requires": {
+				"body-parser": "^1.19.0",
+				"chalk": "^4.1.1",
+				"express": "^4.17.1",
+				"express-async-errors": "^3.1.1",
+				"helmet": "^4.4.1",
+				"missing-native-js-functions": "^1.1.8"
+			}
+		},
+		"load-json-file": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+			"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+			"dev": true,
+			"requires": {
+				"graceful-fs": "^4.1.2",
+				"parse-json": "^2.2.0",
+				"pify": "^2.0.0",
+				"pinkie-promise": "^2.0.0",
+				"strip-bom": "^2.0.0"
+			}
+		},
+		"lodash.includes": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+			"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
+		},
+		"lodash.isboolean": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+			"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
+		},
+		"lodash.isinteger": {
+			"version": "4.0.4",
+			"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+			"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
+		},
+		"lodash.isnumber": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+			"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
+		},
+		"lodash.isplainobject": {
+			"version": "4.0.6",
+			"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+			"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+		},
+		"lodash.isstring": {
+			"version": "4.0.1",
+			"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+			"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+		},
+		"lodash.once": {
+			"version": "4.1.1",
+			"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+			"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+		},
+		"loud-rejection": {
+			"version": "1.6.0",
+			"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+			"integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+			"dev": true,
+			"requires": {
+				"currently-unhandled": "^0.4.1",
+				"signal-exit": "^3.0.0"
+			}
+		},
+		"make-error": {
+			"version": "1.3.6",
+			"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+			"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+			"dev": true
+		},
+		"map-obj": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+			"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+			"dev": true
+		},
+		"media-typer": {
+			"version": "0.3.0",
+			"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+			"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+		},
+		"memory-pager": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
+			"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
+			"optional": true
+		},
+		"meow": {
+			"version": "3.7.0",
+			"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+			"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+			"dev": true,
+			"requires": {
+				"camelcase-keys": "^2.0.0",
+				"decamelize": "^1.1.2",
+				"loud-rejection": "^1.0.0",
+				"map-obj": "^1.0.1",
+				"minimist": "^1.1.3",
+				"normalize-package-data": "^2.3.4",
+				"object-assign": "^4.0.1",
+				"read-pkg-up": "^1.0.1",
+				"redent": "^1.0.0",
+				"trim-newlines": "^1.0.0"
+			}
+		},
+		"merge-descriptors": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+			"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+		},
+		"methods": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+			"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+		},
+		"mime": {
+			"version": "1.6.0",
+			"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+			"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
+		},
+		"mime-db": {
+			"version": "1.48.0",
+			"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz",
+			"integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ=="
+		},
+		"mime-types": {
+			"version": "2.1.31",
+			"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz",
+			"integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==",
+			"requires": {
+				"mime-db": "1.48.0"
+			}
+		},
+		"minimatch": {
+			"version": "3.0.4",
+			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+			"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+			"dev": true,
+			"requires": {
+				"brace-expansion": "^1.1.7"
+			}
+		},
+		"minimist": {
+			"version": "1.2.5",
+			"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+			"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+			"dev": true
+		},
+		"missing-native-js-functions": {
+			"version": "1.2.7",
+			"resolved": "https://registry.npmjs.org/missing-native-js-functions/-/missing-native-js-functions-1.2.7.tgz",
+			"integrity": "sha512-3JT72wOtgojsdmUaa/LIlEuPmT802Kajnr9RFxSZFCX37oL3epd3mZwSaabqFHxPOUW7nJnix+BAWKwX6O0Q5g=="
+		},
+		"mkdirp": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+			"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+			"dev": true
+		},
+		"mongodb": {
+			"version": "3.6.9",
+			"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.9.tgz",
+			"integrity": "sha512-1nSCKgSunzn/CXwgOWgbPHUWOO5OfERcuOWISmqd610jn0s8BU9K4879iJVabqgpPPbA6hO7rG48eq+fGED3Mg==",
+			"requires": {
+				"bl": "^2.2.1",
+				"bson": "^1.1.4",
+				"denque": "^1.4.1",
+				"optional-require": "^1.0.3",
+				"safe-buffer": "^5.1.2",
+				"saslprep": "^1.0.0"
+			}
+		},
+		"mongoose": {
+			"version": "5.12.12",
+			"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.12.12.tgz",
+			"integrity": "sha512-n+ZmGApaL5x/r92w6S4pb+c075i+YKzg1F9YWkznSzQMtvetj/2dSjj2cqsITpd6z60k3K7ZaosIl6hzHwUA9g==",
+			"requires": {
+				"@types/mongodb": "^3.5.27",
+				"bson": "^1.1.4",
+				"kareem": "2.3.2",
+				"mongodb": "3.6.8",
+				"mongoose-legacy-pluralize": "1.0.2",
+				"mpath": "0.8.3",
+				"mquery": "3.2.5",
+				"ms": "2.1.2",
+				"regexp-clone": "1.0.0",
+				"safe-buffer": "5.2.1",
+				"sift": "13.5.2",
+				"sliced": "1.0.1"
+			},
+			"dependencies": {
+				"mongodb": {
+					"version": "3.6.8",
+					"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.8.tgz",
+					"integrity": "sha512-sDjJvI73WjON1vapcbyBD3Ao9/VN3TKYY8/QX9EPbs22KaCSrQ5rXo5ZZd44tWJ3wl3FlnrFZ+KyUtNH6+1ZPQ==",
+					"requires": {
+						"bl": "^2.2.1",
+						"bson": "^1.1.4",
+						"denque": "^1.4.1",
+						"optional-require": "^1.0.3",
+						"safe-buffer": "^5.1.2",
+						"saslprep": "^1.0.0"
+					}
+				},
+				"ms": {
+					"version": "2.1.2",
+					"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+					"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+				}
+			}
+		},
+		"mongoose-autopopulate": {
+			"version": "0.12.3",
+			"resolved": "https://registry.npmjs.org/mongoose-autopopulate/-/mongoose-autopopulate-0.12.3.tgz",
+			"integrity": "sha512-yNmYsfi6OpS/GQ+48mkB0KQ199ExHmmPrt3wt3fyxPHPMtEBGts7yq3wBQR6VgKCPOQaKvCI1URbJCPOtrPeLw==",
+			"requires": {}
+		},
+		"mongoose-legacy-pluralize": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
+			"integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==",
+			"requires": {}
+		},
+		"mpath": {
+			"version": "0.8.3",
+			"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz",
+			"integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA=="
+		},
+		"mquery": {
+			"version": "3.2.5",
+			"resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz",
+			"integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==",
+			"requires": {
+				"bluebird": "3.5.1",
+				"debug": "3.1.0",
+				"regexp-clone": "^1.0.0",
+				"safe-buffer": "5.1.2",
+				"sliced": "1.0.1"
+			},
+			"dependencies": {
+				"debug": {
+					"version": "3.1.0",
+					"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+					"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+					"requires": {
+						"ms": "2.0.0"
+					}
+				},
+				"ms": {
+					"version": "2.0.0",
+					"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+					"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+				},
+				"safe-buffer": {
+					"version": "5.1.2",
+					"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+					"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+				}
+			}
+		},
+		"ms": {
+			"version": "2.1.3",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+			"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+		},
+		"nan": {
+			"version": "2.14.2",
+			"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
+			"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
+			"dev": true
+		},
+		"negotiator": {
+			"version": "0.6.2",
+			"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+			"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+		},
+		"node-fetch": {
+			"version": "2.6.1",
+			"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
+			"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
+		},
+		"normalize-package-data": {
+			"version": "2.5.0",
+			"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+			"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+			"dev": true,
+			"requires": {
+				"hosted-git-info": "^2.1.4",
+				"resolve": "^1.10.0",
+				"semver": "2 || 3 || 4 || 5",
+				"validate-npm-package-license": "^3.0.1"
+			}
+		},
+		"normalize-path": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+			"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+			"dev": true
+		},
+		"object-assign": {
+			"version": "4.1.1",
+			"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+			"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+			"dev": true
+		},
+		"on-finished": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+			"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+			"requires": {
+				"ee-first": "1.1.1"
+			}
+		},
+		"once": {
+			"version": "1.4.0",
+			"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+			"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+			"dev": true,
+			"requires": {
+				"wrappy": "1"
+			}
+		},
+		"optional-require": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
+			"integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA=="
+		},
+		"parse-json": {
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+			"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+			"dev": true,
+			"requires": {
+				"error-ex": "^1.2.0"
+			}
+		},
+		"parseurl": {
+			"version": "1.3.3",
+			"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+			"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+		},
+		"path-exists": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+			"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+			"dev": true,
+			"requires": {
+				"pinkie-promise": "^2.0.0"
+			}
+		},
+		"path-is-absolute": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+			"dev": true
+		},
+		"path-parse": {
+			"version": "1.0.7",
+			"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+			"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+			"dev": true
+		},
+		"path-to-regexp": {
+			"version": "0.1.7",
+			"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+			"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+		},
+		"path-type": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+			"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+			"dev": true,
+			"requires": {
+				"graceful-fs": "^4.1.2",
+				"pify": "^2.0.0",
+				"pinkie-promise": "^2.0.0"
+			}
+		},
+		"picomatch": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+			"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
+			"dev": true
+		},
+		"pify": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+			"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+			"dev": true
+		},
+		"pinkie": {
+			"version": "2.0.4",
+			"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+			"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+			"dev": true
+		},
+		"pinkie-promise": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+			"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+			"dev": true,
+			"requires": {
+				"pinkie": "^2.0.0"
+			}
+		},
+		"process-nextick-args": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+			"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+		},
+		"proxy-addr": {
+			"version": "2.0.7",
+			"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+			"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+			"requires": {
+				"forwarded": "0.2.0",
+				"ipaddr.js": "1.9.1"
+			}
+		},
+		"punycode": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+			"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+		},
+		"qs": {
+			"version": "6.7.0",
+			"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+			"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+		},
+		"querystringify": {
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+			"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
+		},
+		"range-parser": {
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+			"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
+		},
+		"raw-body": {
+			"version": "2.4.0",
+			"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+			"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+			"requires": {
+				"bytes": "3.1.0",
+				"http-errors": "1.7.2",
+				"iconv-lite": "0.4.24",
+				"unpipe": "1.0.0"
+			}
+		},
+		"read-pkg": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+			"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+			"dev": true,
+			"requires": {
+				"load-json-file": "^1.0.0",
+				"normalize-package-data": "^2.3.2",
+				"path-type": "^1.0.0"
+			}
+		},
+		"read-pkg-up": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+			"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+			"dev": true,
+			"requires": {
+				"find-up": "^1.0.0",
+				"read-pkg": "^1.0.0"
+			}
+		},
+		"readable-stream": {
+			"version": "2.3.7",
+			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+			"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+			"requires": {
+				"core-util-is": "~1.0.0",
+				"inherits": "~2.0.3",
+				"isarray": "~1.0.0",
+				"process-nextick-args": "~2.0.0",
+				"safe-buffer": "~5.1.1",
+				"string_decoder": "~1.1.1",
+				"util-deprecate": "~1.0.1"
+			},
+			"dependencies": {
+				"safe-buffer": {
+					"version": "5.1.2",
+					"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+					"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+				}
+			}
+		},
+		"readdirp": {
+			"version": "3.5.0",
+			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
+			"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
+			"dev": true,
+			"requires": {
+				"picomatch": "^2.2.1"
+			}
+		},
+		"redent": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+			"integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+			"dev": true,
+			"requires": {
+				"indent-string": "^2.1.0",
+				"strip-indent": "^1.0.1"
+			}
+		},
+		"regexp-clone": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
+			"integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw=="
+		},
+		"repeating": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+			"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+			"dev": true,
+			"requires": {
+				"is-finite": "^1.0.0"
+			}
+		},
+		"require-from-string": {
+			"version": "2.0.2",
+			"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+			"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
+		},
+		"requires-port": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+			"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
+		},
+		"resolve": {
+			"version": "1.20.0",
+			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+			"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+			"dev": true,
+			"requires": {
+				"is-core-module": "^2.2.0",
+				"path-parse": "^1.0.6"
+			}
+		},
+		"rimraf": {
+			"version": "2.7.1",
+			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+			"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+			"dev": true,
+			"requires": {
+				"glob": "^7.1.3"
+			}
+		},
+		"safe-buffer": {
+			"version": "5.2.1",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+			"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+		},
+		"safer-buffer": {
+			"version": "2.1.2",
+			"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+			"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+		},
+		"saslprep": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
+			"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
+			"optional": true,
+			"requires": {
+				"sparse-bitfield": "^3.0.3"
+			}
+		},
+		"semver": {
+			"version": "5.7.1",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+			"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+		},
+		"send": {
+			"version": "0.17.1",
+			"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+			"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+			"requires": {
+				"debug": "2.6.9",
+				"depd": "~1.1.2",
+				"destroy": "~1.0.4",
+				"encodeurl": "~1.0.2",
+				"escape-html": "~1.0.3",
+				"etag": "~1.8.1",
+				"fresh": "0.5.2",
+				"http-errors": "~1.7.2",
+				"mime": "1.6.0",
+				"ms": "2.1.1",
+				"on-finished": "~2.3.0",
+				"range-parser": "~1.2.1",
+				"statuses": "~1.5.0"
+			},
+			"dependencies": {
+				"ms": {
+					"version": "2.1.1",
+					"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+					"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+				}
+			}
+		},
+		"serve-static": {
+			"version": "1.14.1",
+			"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+			"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+			"requires": {
+				"encodeurl": "~1.0.2",
+				"escape-html": "~1.0.3",
+				"parseurl": "~1.3.3",
+				"send": "0.17.1"
+			}
+		},
+		"setprototypeof": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+			"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+		},
+		"sift": {
+			"version": "13.5.2",
+			"resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz",
+			"integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA=="
+		},
+		"signal-exit": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+			"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+			"dev": true
+		},
+		"sliced": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
+			"integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
+		},
+		"source-map": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+			"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+			"dev": true
+		},
+		"source-map-support": {
+			"version": "0.5.19",
+			"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+			"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+			"dev": true,
+			"requires": {
+				"buffer-from": "^1.0.0",
+				"source-map": "^0.6.0"
+			}
+		},
+		"sparse-bitfield": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
+			"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
+			"optional": true,
+			"requires": {
+				"memory-pager": "^1.0.2"
+			}
+		},
+		"spdx-correct": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+			"integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+			"dev": true,
+			"requires": {
+				"spdx-expression-parse": "^3.0.0",
+				"spdx-license-ids": "^3.0.0"
+			}
+		},
+		"spdx-exceptions": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+			"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+			"dev": true
+		},
+		"spdx-expression-parse": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+			"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+			"dev": true,
+			"requires": {
+				"spdx-exceptions": "^2.1.0",
+				"spdx-license-ids": "^3.0.0"
+			}
+		},
+		"spdx-license-ids": {
+			"version": "3.0.9",
+			"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz",
+			"integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==",
+			"dev": true
+		},
+		"statuses": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+			"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+		},
+		"string_decoder": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+			"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+			"requires": {
+				"safe-buffer": "~5.1.0"
+			},
+			"dependencies": {
+				"safe-buffer": {
+					"version": "5.1.2",
+					"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+					"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+				}
+			}
+		},
+		"strip-bom": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+			"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+			"dev": true,
+			"requires": {
+				"is-utf8": "^0.2.0"
+			}
+		},
+		"strip-indent": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+			"integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+			"dev": true,
+			"requires": {
+				"get-stdin": "^4.0.1"
+			}
+		},
+		"strip-json-comments": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+			"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+			"dev": true
+		},
+		"supports-color": {
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+			"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+			"requires": {
+				"has-flag": "^4.0.0"
+			}
+		},
+		"to-regex-range": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+			"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+			"dev": true,
+			"requires": {
+				"is-number": "^7.0.0"
+			}
+		},
+		"toidentifier": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+			"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+		},
+		"tree-kill": {
+			"version": "1.2.2",
+			"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+			"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+			"dev": true
+		},
+		"trim-newlines": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+			"integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+			"dev": true
+		},
+		"ts-node": {
+			"version": "9.1.1",
+			"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz",
+			"integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==",
+			"dev": true,
+			"requires": {
+				"arg": "^4.1.0",
+				"create-require": "^1.1.0",
+				"diff": "^4.0.1",
+				"make-error": "^1.1.1",
+				"source-map-support": "^0.5.17",
+				"yn": "3.1.1"
+			}
+		},
+		"ts-node-dev": {
+			"version": "1.1.6",
+			"resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.1.6.tgz",
+			"integrity": "sha512-RTUi7mHMNQospArGz07KiraQcdgUVNXKsgO2HAi7FoiyPMdTDqdniB6K1dqyaIxT7c9v/VpSbfBZPS6uVpaFLQ==",
+			"dev": true,
+			"requires": {
+				"chokidar": "^3.5.1",
+				"dateformat": "~1.0.4-1.2.3",
+				"dynamic-dedupe": "^0.3.0",
+				"minimist": "^1.2.5",
+				"mkdirp": "^1.0.4",
+				"resolve": "^1.0.0",
+				"rimraf": "^2.6.1",
+				"source-map-support": "^0.5.12",
+				"tree-kill": "^1.2.2",
+				"ts-node": "^9.0.0",
+				"tsconfig": "^7.0.0"
+			}
+		},
+		"tsconfig": {
+			"version": "7.0.0",
+			"resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
+			"integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
+			"dev": true,
+			"requires": {
+				"@types/strip-bom": "^3.0.0",
+				"@types/strip-json-comments": "0.0.30",
+				"strip-bom": "^3.0.0",
+				"strip-json-comments": "^2.0.0"
+			},
+			"dependencies": {
+				"strip-bom": {
+					"version": "3.0.0",
+					"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+					"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+					"dev": true
+				}
+			}
+		},
+		"type-is": {
+			"version": "1.6.18",
+			"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+			"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+			"requires": {
+				"media-typer": "0.3.0",
+				"mime-types": "~2.1.24"
+			}
+		},
+		"typescript": {
+			"version": "4.3.2",
+			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
+			"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw=="
+		},
+		"unpipe": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+			"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+		},
+		"uri-js": {
+			"version": "4.4.1",
+			"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+			"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+			"requires": {
+				"punycode": "^2.1.0"
+			}
+		},
+		"url-parse": {
+			"version": "1.5.3",
+			"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
+			"integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
+			"requires": {
+				"querystringify": "^2.1.1",
+				"requires-port": "^1.0.0"
+			}
+		},
+		"util-deprecate": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+			"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+		},
+		"utils-merge": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+			"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+		},
+		"uuid": {
+			"version": "8.3.2",
+			"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+			"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
+		},
+		"validate-npm-package-license": {
+			"version": "3.0.4",
+			"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+			"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+			"dev": true,
+			"requires": {
+				"spdx-correct": "^3.0.0",
+				"spdx-expression-parse": "^3.0.0"
+			}
+		},
+		"vary": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+			"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+		},
+		"wrappy": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+			"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+			"dev": true
+		},
+		"ws": {
+			"version": "7.4.6",
+			"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+			"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
+			"requires": {}
+		},
+		"xtend": {
+			"version": "4.0.2",
+			"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+			"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+			"dev": true
+		},
+		"yn": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+			"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+			"dev": true
+		}
+	}
+}
diff --git a/gateway/package.json b/gateway/package.json
new file mode 100644
index 00000000..4a6043d6
--- /dev/null
+++ b/gateway/package.json
@@ -0,0 +1,38 @@
+{
+	"name": "@fosscord/gateway",
+	"version": "1.0.0",
+	"description": "",
+	"main": "dist/index.js",
+	"scripts": {
+		"test": "echo \"Error: no test specified\" && exit 1",
+		"start": "npm run build && node dist/start.js",
+		"build": "npx tsc -b .",
+		"dev": "tsnd --respawn src/start.ts"
+	},
+	"keywords": [],
+	"author": "Fosscord",
+	"license": "ISC",
+	"dependencies": {
+		"@fosscord/server-util": "^1.3.51",
+		"ajv": "^8.5.0",
+		"amqplib": "^0.8.0",
+		"dotenv": "^8.2.0",
+		"jsonwebtoken": "^8.5.1",
+		"lambert-server": "^1.2.8",
+		"missing-native-js-functions": "^1.2.3",
+		"mongoose-autopopulate": "^0.12.3",
+		"node-fetch": "^2.6.1",
+		"typescript": "^4.2.3",
+		"uuid": "^8.3.2",
+		"ws": "^7.4.2"
+	},
+	"devDependencies": {
+		"@types/amqplib": "^0.8.1",
+		"@types/jsonwebtoken": "^8.5.0",
+		"@types/mongoose-autopopulate": "^0.10.1",
+		"@types/uuid": "^8.3.0",
+		"@types/ws": "^7.4.0",
+		"erlpack": "^0.1.3",
+		"ts-node-dev": "^1.1.6"
+	}
+}
diff --git a/gateway/src/Server.ts b/gateway/src/Server.ts
new file mode 100644
index 00000000..d4b3271c
--- /dev/null
+++ b/gateway/src/Server.ts
@@ -0,0 +1,55 @@
+import "missing-native-js-functions";
+import dotenv from "dotenv";
+dotenv.config();
+import { Config, db, RabbitMQ } from "@fosscord/server-util";
+import { Server as WebSocketServer } from "ws";
+import { Connection } from "./events/Connection";
+import http from "http";
+
+export class Server {
+	public ws: WebSocketServer;
+	public port: number;
+	public server: http.Server;
+	public production: boolean;
+
+	constructor({ port, server, production }: { port: number; server?: http.Server; production?: boolean }) {
+		this.port = port;
+		this.production = production || false;
+
+		if (server) this.server = server;
+		else
+			this.server = http.createServer(function (req, res) {
+				res.writeHead(200).end("Online");
+			});
+
+		this.ws = new WebSocketServer({
+			maxPayload: 4096,
+			server: this.server,
+		});
+		this.ws.on("connection", Connection);
+		this.ws.on("error", console.error);
+	}
+
+	async setupSchema() {
+		// TODO: adjust expireAfterSeconds -> lower
+		await Promise.all([db.collection("events").createIndex({ created_at: 1 }, { expireAfterSeconds: 60 })]);
+	}
+
+	async start(): Promise<void> {
+		// @ts-ignore
+		await (db as Promise<Connection>);
+		await this.setupSchema();
+		await Config.init();
+		await RabbitMQ.init();
+		console.log("[Database] connected");
+		if (!this.server.listening) {
+			this.server.listen(this.port);
+			console.log(`[Gateway] online on 0.0.0.0:${this.port}`);
+		}
+	}
+
+	async stop() {
+		await db.close();
+		this.server.close();
+	}
+}
diff --git a/gateway/src/events/Close.ts b/gateway/src/events/Close.ts
new file mode 100644
index 00000000..f819b064
--- /dev/null
+++ b/gateway/src/events/Close.ts
@@ -0,0 +1,6 @@
+import WebSocket from "ws";
+import { Message } from "./Message";
+
+export function Close(this: WebSocket, code: number, reason: string) {
+	this.off("message", Message);
+}
diff --git a/gateway/src/events/Connection.ts b/gateway/src/events/Connection.ts
new file mode 100644
index 00000000..1ef9fb48
--- /dev/null
+++ b/gateway/src/events/Connection.ts
@@ -0,0 +1,62 @@
+import WebSocket, { Server } from "../util/WebSocket";
+import { IncomingMessage } from "http";
+import { Close } from "./Close";
+import { Message } from "./Message";
+import { setHeartbeat } from "../util/setHeartbeat";
+import { Send } from "../util/Send";
+import { CLOSECODES, OPCODES } from "../util/Constants";
+import { createDeflate } from "zlib";
+var erlpack: any;
+try {
+	erlpack = require("erlpack");
+} catch (error) {}
+
+// TODO: check rate limit
+// TODO: specify rate limit in config
+// TODO: check msg max size
+
+export async function Connection(this: Server, socket: WebSocket, request: IncomingMessage) {
+	try {
+		socket.on("close", Close);
+		socket.on("message", Message);
+
+		const { searchParams } = new URL(`http://localhost${request.url}`);
+		// @ts-ignore
+		socket.encoding = searchParams.get("encoding") || "json";
+		if (!["json", "etf"].includes(socket.encoding)) {
+			if (socket.encoding === "etf" && erlpack) throw new Error("Erlpack is not installed: 'npm i -D erlpack'");
+			return socket.close(CLOSECODES.Decode_error);
+		}
+
+		// @ts-ignore
+		socket.version = Number(searchParams.get("version")) || 8;
+		if (socket.version != 8) return socket.close(CLOSECODES.Invalid_API_version);
+
+		// @ts-ignore
+		socket.compress = searchParams.get("compress") || "";
+		if (socket.compress) {
+			if (socket.compress !== "zlib-stream") return socket.close(CLOSECODES.Decode_error);
+			socket.deflate = createDeflate({ chunkSize: 65535 });
+			socket.deflate.on("data", (chunk) => socket.send(chunk));
+		}
+
+		socket.permissions = {};
+		socket.sequence = 0;
+
+		setHeartbeat(socket);
+
+		await Send(socket, {
+			op: OPCODES.Hello,
+			d: {
+				heartbeat_interval: 1000 * 30,
+			},
+		});
+
+		socket.readyTimeout = setTimeout(() => {
+			return socket.close(CLOSECODES.Session_timed_out);
+		}, 1000 * 30);
+	} catch (error) {
+		console.error(error);
+		return socket.close(CLOSECODES.Unknown_error);
+	}
+}
diff --git a/gateway/src/events/Message.ts b/gateway/src/events/Message.ts
new file mode 100644
index 00000000..2ca82b3c
--- /dev/null
+++ b/gateway/src/events/Message.ts
@@ -0,0 +1,45 @@
+import WebSocket, { Data } from "../util/WebSocket";
+var erlpack: any;
+try {
+	erlpack = require("erlpack");
+} catch (error) {}
+import OPCodeHandlers from "../opcodes";
+import { Payload, CLOSECODES } from "../util/Constants";
+import { instanceOf, Tuple } from "lambert-server";
+import { check } from "../opcodes/instanceOf";
+
+const PayloadSchema = {
+	op: Number,
+	$d: new Tuple(Object, Number), // or number for heartbeat sequence
+	$s: Number,
+	$t: String,
+};
+
+export async function Message(this: WebSocket, buffer: Data) {
+	// TODO: compression
+	var data: Payload;
+
+	if (this.encoding === "etf" && buffer instanceof Buffer) data = erlpack.unpack(buffer);
+	else if (this.encoding === "json" && typeof buffer === "string") data = JSON.parse(buffer);
+	else return;
+
+	check.call(this, PayloadSchema, data);
+
+	// @ts-ignore
+	const OPCodeHandler = OPCodeHandlers[data.op];
+	if (!OPCodeHandler) {
+		console.error("Unknown_opcode: " + data.op);
+		// TODO: if all opcodes are implemented comment this out:
+		// this.close(CLOSECODES.Unknown_opcode);
+		return;
+	}
+
+	console.log("got: " + OPCodeHandler.name);
+
+	try {
+		return await OPCodeHandler.call(this, data);
+	} catch (error) {
+		console.error(error);
+		if (!this.CLOSED && this.CLOSING) return this.close(CLOSECODES.Unknown_error);
+	}
+}
diff --git a/gateway/src/index.ts b/gateway/src/index.ts
new file mode 100644
index 00000000..7513bd2f
--- /dev/null
+++ b/gateway/src/index.ts
@@ -0,0 +1 @@
+export * from "./Server";
diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts
new file mode 100644
index 00000000..6a6967d6
--- /dev/null
+++ b/gateway/src/listener/listener.ts
@@ -0,0 +1,382 @@
+import {
+	db,
+	Event,
+	MongooseCache,
+	UserModel,
+	getPermission,
+	Permissions,
+	ChannelModel,
+	RabbitMQ,
+	EVENT,
+} from "@fosscord/server-util";
+import { OPCODES } from "../util/Constants";
+import { Send } from "../util/Send";
+import WebSocket from "../util/WebSocket";
+import "missing-native-js-functions";
+import { ConsumeMessage } from "amqplib";
+
+// TODO: close connection on Invalidated Token
+// TODO: check intent
+// TODO: Guild Member Update is sent for current-user updates regardless of whether the GUILD_MEMBERS intent is set.
+// ? How to resubscribe MongooseCache for new dm channel events? Maybe directly send them to the user_id regardless of the channel_id? -> max overhead of creating 10 events in database for dm user group. Or a new field in event -> recipient_ids?
+
+// Sharding: calculate if the current shard id matches the formula: shard_id = (guild_id >> 22) % num_shards
+// https://discord.com/developers/docs/topics/gateway#sharding
+
+export interface DispatchOpts {
+	eventStream: MongooseCache;
+	guilds: Array<string>;
+}
+
+function getPipeline(this: WebSocket, guilds: string[], channels: string[] = []) {
+	if (this.shard_count) {
+		guilds = guilds.filter((x) => (BigInt(x) >> 22n) % this.shard_count! === this.shard_id);
+	}
+
+	return [
+		{
+			$match: {
+				$or: [
+					{ "fullDocument.guild_id": { $in: guilds } },
+					{ "fullDocument.user_id": this.user_id },
+					{ "fullDocument.channel_id": { $in: channels } },
+				],
+			},
+		},
+	];
+}
+
+async function rabbitListen(this: WebSocket, id: string) {
+	await this.rabbitCh!.assertExchange(id, "fanout", { durable: false });
+	const q = await this.rabbitCh!.assertQueue("", { exclusive: true, autoDelete: true });
+
+	this.rabbitCh!.bindQueue(q.queue, id, "");
+	this.rabbitCh!.consume(q.queue, consume.bind(this), {
+		noAck: false,
+	});
+	this.rabbitCh!.queues[id] = q.queue;
+}
+
+// TODO: use already required guilds/channels of Identify and don't fetch them again
+export async function setupListener(this: WebSocket) {
+	const user = await UserModel.findOne({ id: this.user_id }, { guilds: true }).exec();
+	const channels = await ChannelModel.find(
+		{ $or: [{ recipient_ids: this.user_id }, { guild_id: { $in: user.guilds } }] },
+		{ id: true, permission_overwrites: true }
+	).exec();
+	const dm_channels = channels.filter((x) => !x.guild_id);
+	const guild_channels = channels.filter((x) => x.guild_id);
+
+	if (RabbitMQ.connection) {
+		// @ts-ignore
+		this.rabbitCh = await RabbitMQ.connection.createChannel();
+		this.rabbitCh!.queues = {};
+
+		rabbitListen.call(this, this.user_id);
+
+		for (const channel of dm_channels) {
+			rabbitListen.call(this, channel.id);
+		}
+		for (const guild of user.guilds) {
+			// contains guild and dm channels
+
+			getPermission(this.user_id, guild)
+				.then((x) => {
+					this.permissions[guild] = x;
+					rabbitListen.call(this, guild);
+					for (const channel of guild_channels) {
+						if (x.overwriteChannel(channel.permission_overwrites).has("VIEW_CHANNEL")) {
+							rabbitListen.call(this, channel.id);
+						}
+					}
+				})
+				.catch((e) => {});
+		}
+
+		this.once("close", () => {
+			this.rabbitCh!.close();
+		});
+	} else {
+		const eventStream = new MongooseCache(
+			db.collection("events"),
+			getPipeline.call(
+				this,
+				user.guilds,
+				channels.map((x) => x.id)
+			),
+			{
+				onlyEvents: true,
+			}
+		);
+
+		await eventStream.init();
+		eventStream.on("insert", (document: Event) =>
+			dispatch.call(this, document, { eventStream, guilds: user.guilds })
+		);
+
+		this.once("close", () => eventStream.destroy());
+	}
+}
+
+// TODO: use rabbitmq to only receive events that are included in intents
+function consume(this: WebSocket, opts: ConsumeMessage | null) {
+	if (!opts) return;
+	if (!this.rabbitCh) return;
+	const data = JSON.parse(opts.content.toString());
+	const id = data.id as string;
+	const event = opts.properties.type as EVENT;
+	const permission = this.permissions[id] || new Permissions("ADMINISTRATOR"); // default permission for dm
+
+	console.log("rabbitmq event", event);
+
+	// subscription managment
+	switch (event) {
+		case "CHANNEL_DELETE":
+		case "GUILD_DELETE":
+			this.rabbitCh.cancel(id);
+			break;
+		case "CHANNEL_CREATE":
+		// TODO: check if user has permission to channel
+		case "GUILD_CREATE":
+			rabbitListen.call(this, id);
+			break;
+		case "CHANNEL_UPDATE":
+			const queue_id = this.rabbitCh.queues[id];
+			// @ts-ignore
+			const exists = this.rabbitCh.consumers[id];
+			if (permission.overwriteChannel(data.permission_overwrites).has("VIEW_CHANNEL")) {
+				if (exists) break;
+				rabbitListen.call(this, id);
+			} else {
+				if (!exists) break;
+				this.rabbitCh.cancel(queue_id);
+				this.rabbitCh.unbindQueue(queue_id, id, "");
+			}
+			break;
+	}
+
+	// permission checking
+	switch (event) {
+		case "INVITE_CREATE":
+		case "INVITE_DELETE":
+		case "GUILD_INTEGRATIONS_UPDATE":
+			if (!permission.has("MANAGE_GUILD")) return;
+			break;
+		case "WEBHOOKS_UPDATE":
+			if (!permission.has("MANAGE_WEBHOOKS")) return;
+			break;
+		case "GUILD_MEMBER_ADD":
+		case "GUILD_MEMBER_REMOVE":
+		case "GUILD_MEMBER_UPDATE":
+		// only send them, if the user subscribed for this part of the member list, or is a bot
+		case "PRESENCE_UPDATE": // exception if user is friend
+			break;
+		case "GUILD_BAN_ADD":
+		case "GUILD_BAN_REMOVE":
+			if (!permission.has("BAN_MEMBERS")) break;
+			break;
+		case "VOICE_STATE_UPDATE":
+		case "MESSAGE_CREATE":
+		case "MESSAGE_DELETE":
+		case "MESSAGE_DELETE_BULK":
+		case "MESSAGE_UPDATE":
+		case "CHANNEL_PINS_UPDATE":
+		case "MESSAGE_REACTION_ADD":
+		case "MESSAGE_REACTION_REMOVE":
+		case "MESSAGE_REACTION_REMOVE_ALL":
+		case "MESSAGE_REACTION_REMOVE_EMOJI":
+		case "TYPING_START":
+			// only gets send if the user is alowed to view the current channel
+			if (!permission.has("VIEW_CHANNEL")) return;
+			break;
+		case "GUILD_CREATE":
+		case "GUILD_DELETE":
+		case "GUILD_UPDATE":
+		case "GUILD_ROLE_CREATE":
+		case "GUILD_ROLE_UPDATE":
+		case "GUILD_ROLE_DELETE":
+		case "CHANNEL_CREATE":
+		case "CHANNEL_DELETE":
+		case "CHANNEL_UPDATE":
+		case "GUILD_EMOJI_UPDATE":
+		case "READY": // will be sent by the gateway
+		case "USER_UPDATE":
+		case "APPLICATION_COMMAND_CREATE":
+		case "APPLICATION_COMMAND_DELETE":
+		case "APPLICATION_COMMAND_UPDATE":
+		default:
+			// always gets sent
+			// Any events not defined in an intent are considered "passthrough" and will always be sent
+			break;
+	}
+
+	Send(this, {
+		op: OPCODES.Dispatch,
+		t: event,
+		d: data,
+		s: this.sequence++,
+	});
+	this.rabbitCh.ack(opts);
+}
+
+// TODO: cache permission
+// we shouldn't fetch the permission for every event, as a message send event with many channel members would result in many thousand db queries.
+// instead we should calculate all (guild, channel) permissions once and dynamically update if it changes.
+// TODO: only subscribe for events that are in the connection intents
+// TODO: only subscribe for channel/guilds that the user has access to (and re-subscribe if it changes)
+
+export async function dispatch(this: WebSocket, document: Event, { eventStream, guilds }: DispatchOpts) {
+	var permission = new Permissions("ADMINISTRATOR"); // default permission for dms
+	console.log("event", document);
+	var channel_id = document.channel_id || document.data?.channel_id;
+	// TODO: clean up
+	if (document.event === "GUILD_CREATE") {
+		guilds.push(document.data.id);
+		eventStream.changeStream(getPipeline.call(this, guilds));
+	} else if (document.event === "GUILD_DELETE") {
+		guilds.remove(document.guild_id!);
+		eventStream.changeStream(getPipeline.call(this, guilds));
+	} else if (document.event === "CHANNEL_DELETE") channel_id = null;
+	if (document.guild_id && !this.intents.has("GUILDS")) return;
+
+	try {
+		permission = await getPermission(this.user_id, document.guild_id, channel_id);
+	} catch (e) {
+		permission = new Permissions();
+	}
+
+	// check intents: https://discord.com/developers/docs/topics/gateway#gateway-intents
+	switch (document.event) {
+		case "GUILD_DELETE":
+		case "GUILD_CREATE":
+		case "GUILD_UPDATE":
+		case "GUILD_ROLE_CREATE":
+		case "GUILD_ROLE_UPDATE":
+		case "GUILD_ROLE_DELETE":
+		case "CHANNEL_CREATE":
+		case "CHANNEL_DELETE":
+		case "CHANNEL_UPDATE":
+			// gets sent if GUILDS intent is set (already checked in if document.guild_id)
+			break;
+		case "GUILD_INTEGRATIONS_UPDATE":
+			if (!this.intents.has("GUILD_INTEGRATIONS")) return;
+			break;
+		case "WEBHOOKS_UPDATE":
+			if (!this.intents.has("GUILD_WEBHOOKS")) return;
+			break;
+		case "GUILD_EMOJI_UPDATE":
+			if (!this.intents.has("GUILD_EMOJIS")) return;
+			break;
+		// only send them, if the user subscribed for this part of the member list, or is a bot
+		case "GUILD_MEMBER_ADD":
+		case "GUILD_MEMBER_REMOVE":
+		case "GUILD_MEMBER_UPDATE":
+			if (!this.intents.has("GUILD_MEMBERS")) return;
+			break;
+		case "VOICE_STATE_UPDATE":
+			if (!this.intents.has("GUILD_VOICE_STATES")) return;
+			break;
+		case "GUILD_BAN_ADD":
+		case "GUILD_BAN_REMOVE":
+			if (!this.intents.has("GUILD_BANS")) return;
+			break;
+		case "INVITE_CREATE":
+		case "INVITE_DELETE":
+			if (!this.intents.has("GUILD_INVITES")) return;
+		case "PRESENCE_UPDATE":
+			if (!this.intents.has("GUILD_PRESENCES")) return;
+			break;
+		case "MESSAGE_CREATE":
+		case "MESSAGE_DELETE":
+		case "MESSAGE_DELETE_BULK":
+		case "MESSAGE_UPDATE":
+		case "CHANNEL_PINS_UPDATE":
+			if (!this.intents.has("GUILD_MESSAGES") && document.guild_id) return;
+			if (!this.intents.has("DIRECT_MESSAGES") && !document.guild_id) return;
+			break;
+		case "MESSAGE_REACTION_ADD":
+		case "MESSAGE_REACTION_REMOVE":
+		case "MESSAGE_REACTION_REMOVE_ALL":
+		case "MESSAGE_REACTION_REMOVE_EMOJI":
+			if (!this.intents.has("GUILD_MESSAGE_REACTIONS") && document.guild_id) return;
+			if (!this.intents.has("DIRECT_MESSAGE_REACTIONS") && !document.guild_id) return;
+			break;
+
+		case "TYPING_START":
+			if (!this.intents.has("GUILD_MESSAGE_TYPING") && document.guild_id) return;
+			if (!this.intents.has("DIRECT_MESSAGE_TYPING") && !document.guild_id) return;
+			break;
+		case "READY": // will be sent by the gateway
+		case "USER_UPDATE":
+		case "APPLICATION_COMMAND_CREATE":
+		case "APPLICATION_COMMAND_DELETE":
+		case "APPLICATION_COMMAND_UPDATE":
+		default:
+			// Any events not defined in an intent are considered "passthrough" and will always be sent to you.
+			break;
+	}
+
+	// check permissions
+	switch (document.event) {
+		case "GUILD_INTEGRATIONS_UPDATE":
+			if (!permission.has("MANAGE_GUILD")) return;
+			break;
+		case "WEBHOOKS_UPDATE":
+			if (!permission.has("MANAGE_WEBHOOKS")) return;
+			break;
+		case "GUILD_MEMBER_ADD":
+		case "GUILD_MEMBER_REMOVE":
+		case "GUILD_MEMBER_UPDATE":
+			// only send them, if the user subscribed for this part of the member list, or is a bot
+			break;
+		case "GUILD_BAN_ADD":
+		case "GUILD_BAN_REMOVE":
+			if (!permission.has("BAN_MEMBERS")) break;
+			break;
+		case "INVITE_CREATE":
+		case "INVITE_DELETE":
+			if (!permission.has("MANAGE_GUILD")) break;
+		case "PRESENCE_UPDATE":
+			break;
+		case "VOICE_STATE_UPDATE":
+		case "MESSAGE_CREATE":
+		case "MESSAGE_DELETE":
+		case "MESSAGE_DELETE_BULK":
+		case "MESSAGE_UPDATE":
+		case "CHANNEL_PINS_UPDATE":
+		case "MESSAGE_REACTION_ADD":
+		case "MESSAGE_REACTION_REMOVE":
+		case "MESSAGE_REACTION_REMOVE_ALL":
+		case "MESSAGE_REACTION_REMOVE_EMOJI":
+		case "TYPING_START":
+			// only gets send if the user is alowed to view the current channel
+			if (!permission.has("VIEW_CHANNEL")) return;
+			break;
+		case "GUILD_CREATE":
+		case "GUILD_DELETE":
+		case "GUILD_UPDATE":
+		case "GUILD_ROLE_CREATE":
+		case "GUILD_ROLE_UPDATE":
+		case "GUILD_ROLE_DELETE":
+		case "CHANNEL_CREATE":
+		case "CHANNEL_DELETE":
+		case "CHANNEL_UPDATE":
+		case "GUILD_EMOJI_UPDATE":
+		case "READY": // will be sent by the gateway
+		case "USER_UPDATE":
+		case "APPLICATION_COMMAND_CREATE":
+		case "APPLICATION_COMMAND_DELETE":
+		case "APPLICATION_COMMAND_UPDATE":
+		default:
+			// always gets sent
+			// Any events not defined in an intent are considered "passthrough" and will always be sent
+			break;
+	}
+
+	return Send(this, {
+		op: OPCODES.Dispatch,
+		t: document.event,
+		d: document.data,
+		s: this.sequence++,
+	});
+}
diff --git a/gateway/src/opcodes/Heartbeat.ts b/gateway/src/opcodes/Heartbeat.ts
new file mode 100644
index 00000000..015257b9
--- /dev/null
+++ b/gateway/src/opcodes/Heartbeat.ts
@@ -0,0 +1,12 @@
+import { CLOSECODES, Payload } from "../util/Constants";
+import { Send } from "../util/Send";
+import { setHeartbeat } from "../util/setHeartbeat";
+import WebSocket from "../util/WebSocket";
+
+export async function onHeartbeat(this: WebSocket, data: Payload) {
+	// TODO: validate payload
+
+	setHeartbeat(this);
+
+	await Send(this, { op: 11 });
+}
diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts
new file mode 100644
index 00000000..43368367
--- /dev/null
+++ b/gateway/src/opcodes/Identify.ts
@@ -0,0 +1,174 @@
+import { CLOSECODES, Payload, OPCODES } from "../util/Constants";
+import WebSocket from "../util/WebSocket";
+import {
+	ChannelModel,
+	checkToken,
+	GuildModel,
+	Intents,
+	MemberDocument,
+	MemberModel,
+	ReadyEventData,
+	UserModel,
+	toObject,
+	EVENTEnum,
+	Config,
+} from "@fosscord/server-util";
+import { setupListener } from "../listener/listener";
+import { IdentifySchema } from "../schema/Identify";
+import { Send } from "../util/Send";
+// import experiments from "./experiments.json";
+const experiments: any = [];
+import { check } from "./instanceOf";
+
+// TODO: bot sharding
+// TODO: check priviliged intents
+// TODO: check if already identified
+
+export async function onIdentify(this: WebSocket, data: Payload) {
+	clearTimeout(this.readyTimeout);
+	check.call(this, IdentifySchema, data.d);
+
+	const identify: IdentifySchema = data.d;
+
+	try {
+		const { jwtSecret } = Config.get().security;
+		var { decoded } = await checkToken(identify.token, jwtSecret); // will throw an error if invalid
+	} catch (error) {
+		console.error("invalid token", error);
+		return this.close(CLOSECODES.Authentication_failed);
+	}
+	this.user_id = decoded.id;
+	if (!identify.intents) identify.intents = 0b11111111111111n;
+	this.intents = new Intents(identify.intents);
+	if (identify.shard) {
+		this.shard_id = identify.shard[0];
+		this.shard_count = identify.shard[1];
+		if (
+			!this.shard_count ||
+			!this.shard_id ||
+			this.shard_id >= this.shard_count ||
+			this.shard_id < 0 ||
+			this.shard_count <= 0
+		) {
+			return this.close(CLOSECODES.Invalid_shard);
+		}
+	}
+
+	const members = toObject(await MemberModel.find({ id: this.user_id }).exec());
+	const merged_members = members.map((x: any) => {
+		const y = { ...x, user_id: x.id };
+		delete y.settings;
+		delete y.id;
+		return [y];
+	}) as MemberDocument[][];
+	const user_guild_settings_entries = members.map((x) => x.settings);
+
+	const channels = await ChannelModel.find({ recipient_ids: this.user_id }).exec();
+	const user = await UserModel.findOne({ id: this.user_id }).exec();
+	if (!user) return this.close(CLOSECODES.Authentication_failed);
+
+	const public_user = {
+		username: user.username,
+		discriminator: user.discriminator,
+		id: user.id,
+		public_flags: user.public_flags,
+		avatar: user.avatar,
+		bot: user.bot,
+	};
+
+	const guilds = await GuildModel.find({ id: { $in: user.guilds } })
+		.populate({ path: "joined_at", match: { id: this.user_id } })
+		.exec();
+
+	const privateUser = {
+		avatar: user.avatar,
+		mobile: user.mobile,
+		desktop: user.desktop,
+		discriminator: user.discriminator,
+		email: user.email,
+		flags: user.flags,
+		id: user.id,
+		mfa_enabled: user.mfa_enabled,
+		nsfw_allowed: user.nsfw_allowed,
+		phone: user.phone,
+		premium: user.premium,
+		premium_type: user.premium_type,
+		public_flags: user.public_flags,
+		username: user.username,
+		verified: user.verified,
+		bot: user.bot,
+		accent_color: user.accent_color || 0,
+		banner: user.banner,
+	};
+
+	const d: ReadyEventData = {
+		v: 8,
+		user: privateUser,
+		user_settings: user.user_settings,
+		// @ts-ignore
+		guilds: toObject(guilds).map((x) => {
+			// @ts-ignore
+			x.guild_hashes = {
+				channels: { omitted: false, hash: "y4PV2fZ0gmo" },
+				metadata: { omitted: false, hash: "bs1/ckvud3Y" },
+				roles: { omitted: false, hash: "SxA+c5CaYpo" },
+				version: 1,
+			};
+			return x;
+		}),
+		guild_experiments: [], // TODO
+		geo_ordered_rtc_regions: [], // TODO
+		relationships: user.user_data.relationships,
+		read_state: {
+			// TODO
+			entries: [],
+			partial: false,
+			version: 304128,
+		},
+		user_guild_settings: {
+			entries: user_guild_settings_entries,
+			partial: false, // TODO partial
+			version: 642,
+		},
+		// @ts-ignore
+		private_channels: toObject(channels).map((x: ChannelDocument) => {
+			x.recipient_ids = x.recipients.map((y: any) => y.id);
+			delete x.recipients;
+			return x;
+		}),
+		session_id: "", // TODO
+		analytics_token: "", // TODO
+		connected_accounts: [], // TODO
+		consents: {
+			personalization: {
+				consented: false, // TODO
+			},
+		},
+		country_code: user.user_settings.locale,
+		friend_suggestion_count: 0, // TODO
+		// @ts-ignore
+		experiments: experiments, // TODO
+		guild_join_requests: [], // TODO what is this?
+		users: [
+			public_user,
+			...toObject(channels)
+				.map((x: any) => x.recipients)
+				.flat(),
+		].unique(), // TODO
+		merged_members: merged_members,
+		// shard // TODO: only for bots sharding
+		// application // TODO for applications
+	};
+
+	console.log("Send ready");
+
+	// TODO: send real proper data structure
+	await Send(this, {
+		op: OPCODES.Dispatch,
+		t: EVENTEnum.Ready,
+		s: this.sequence++,
+		d,
+	});
+
+	await setupListener.call(this);
+}
diff --git a/gateway/src/opcodes/LazyRequest.ts b/gateway/src/opcodes/LazyRequest.ts
new file mode 100644
index 00000000..b1d553b9
--- /dev/null
+++ b/gateway/src/opcodes/LazyRequest.ts
@@ -0,0 +1,105 @@
+// @ts-nocheck WIP
+import {
+	db,
+	getPermission,
+	MemberModel,
+	MongooseCache,
+	PublicUserProjection,
+	RoleModel,
+	toObject,
+} from "@fosscord/server-util";
+import { LazyRequest } from "../schema/LazyRequest";
+import { OPCODES, Payload } from "../util/Constants";
+import { Send } from "../util/Send";
+import WebSocket from "../util/WebSocket";
+import { check } from "./instanceOf";
+
+// TODO: check permission and only show roles/members that have access to this channel
+// TODO: config: if want to list all members (even those who are offline) sorted by role, or just those who are online
+
+export async function onLazyRequest(this: WebSocket, { d }: Payload) {
+	// TODO: check data
+	check.call(this, LazyRequest, d);
+	const { guild_id, typing, channels, activities } = d as LazyRequest;
+
+	const permissions = await getPermission(this.user_id, guild_id);
+	permissions.hasThrow("VIEW_CHANNEL");
+
+	// MongoDB query to retrieve all hoisted roles and join them with the members and users collection
+	const roles = toObject(
+		await db
+			.collection("roles")
+			.aggregate([
+				{
+					$match: {
+						guild_id,
+						// hoist: true // TODO: also match @everyone role
+					},
+				},
+				{ $sort: { position: 1 } },
+				{
+					$lookup: {
+						from: "members",
+						let: { id: "$id" },
+						pipeline: [
+							{ $match: { $expr: { $in: ["$$id", "$roles"] } } },
+							{ $limit: 100 },
+							{
+								$lookup: {
+									from: "users",
+									let: { user_id: "$id" },
+									pipeline: [
+										{ $match: { $expr: { $eq: ["$id", "$$user_id"] } } },
+										{ $project: PublicUserProjection },
+									],
+									as: "user",
+								},
+							},
+							{
+								$unwind: "$user",
+							},
+						],
+						as: "members",
+					},
+				},
+			])
+			.toArray()
+	);
+
+	const groups = roles.map((x) => ({ id: x.id === guild_id ? "online" : x.id, count: x.members.length }));
+	const member_count = roles.reduce((a, b) => b.members.length + a, 0);
+	const items = [];
+
+	for (const role of roles) {
+		items.push({
+			group: {
+				count: role.members.length,
+				id: role.id === guild_id ? "online" : role.name,
+			},
+		});
+		for (const member of role.members) {
+			member.roles.remove(guild_id);
+			items.push({ member });
+		}
+	}
+
+	return Send(this, {
+		op: OPCODES.Dispatch,
+		s: this.sequence++,
+		t: "GUILD_MEMBER_LIST_UPDATE",
+		d: {
+			ops: [
+				{
+					range: [0, 99],
+					op: "SYNC",
+					items,
+				},
+			],
+			online_count: member_count, // TODO count online count
+			member_count,
+			id: "everyone",
+			guild_id,
+			groups,
+		},
+	});
+}
diff --git a/gateway/src/opcodes/PresenceUpdate.ts b/gateway/src/opcodes/PresenceUpdate.ts
new file mode 100644
index 00000000..3760f8a3
--- /dev/null
+++ b/gateway/src/opcodes/PresenceUpdate.ts
@@ -0,0 +1,6 @@
+import { CLOSECODES, Payload } from "../util/Constants";
+import WebSocket from "../util/WebSocket";
+
+export function onPresenceUpdate(this: WebSocket, data: Payload) {
+	// return this.close(CLOSECODES.Unknown_error);
+}
diff --git a/gateway/src/opcodes/RequestGuildMembers.ts b/gateway/src/opcodes/RequestGuildMembers.ts
new file mode 100644
index 00000000..2701d978
--- /dev/null
+++ b/gateway/src/opcodes/RequestGuildMembers.ts
@@ -0,0 +1,7 @@
+import { CLOSECODES, Payload } from "../util/Constants";
+
+import WebSocket from "../util/WebSocket";
+
+export function onRequestGuildMembers(this: WebSocket, data: Payload) {
+	// return this.close(CLOSECODES.Unknown_error);
+}
diff --git a/gateway/src/opcodes/Resume.ts b/gateway/src/opcodes/Resume.ts
new file mode 100644
index 00000000..4efde9b0
--- /dev/null
+++ b/gateway/src/opcodes/Resume.ts
@@ -0,0 +1,14 @@
+import { CLOSECODES, Payload } from "../util/Constants";
+import { Send } from "../util/Send";
+
+import WebSocket from "../util/WebSocket";
+
+export async function onResume(this: WebSocket, data: Payload) {
+	console.log("Got Resume -> cancel not implemented");
+	await Send(this, {
+		op: 9,
+		d: false,
+	});
+
+	// return this.close(CLOSECODES.Invalid_session);
+}
diff --git a/gateway/src/opcodes/VoiceStateUpdate.ts b/gateway/src/opcodes/VoiceStateUpdate.ts
new file mode 100644
index 00000000..0d51513d
--- /dev/null
+++ b/gateway/src/opcodes/VoiceStateUpdate.ts
@@ -0,0 +1,26 @@
+import { VoiceStateUpdateSchema } from "../schema/VoiceStateUpdate.ts";
+import { CLOSECODES, Payload } from "../util/Constants";
+import { Send } from "../util/Send";
+
+import WebSocket from "../util/WebSocket";
+import { check } from "./instanceOf";
+// TODO: implementation
+// TODO: check if a voice server is setup
+// TODO: save voice servers in database and retrieve them
+// Notice: Bot users respect the voice channel's user limit, if set. When the voice channel is full, you will not receive the Voice State Update or Voice Server Update events in response to your own Voice State Update. Having MANAGE_CHANNELS permission bypasses this limit and allows you to join regardless of the channel being full or not.
+
+export async function onVoiceStateUpdate(this: WebSocket, data: Payload) {
+	check.call(this, VoiceStateUpdateSchema, data.d);
+	const body = data.d as VoiceStateUpdateSchema;
+
+	await Send(this, {
+		op: 0,
+		s: this.sequence++,
+		t: "VOICE_SERVER_UPDATE",
+		d: {
+			token: ``,
+			guild_id: body.guild_id,
+			endpoint: `localhost:3004`,
+		},
+	});
+}
diff --git a/gateway/src/opcodes/experiments.json b/gateway/src/opcodes/experiments.json
new file mode 100644
index 00000000..0370b5da
--- /dev/null
+++ b/gateway/src/opcodes/experiments.json
@@ -0,0 +1,76 @@
+[
+	[4047587481, 0, 0, -1, 0],
+	[1509401575, 0, 1, -1, 0],
+	[1865079242, 0, 1, -1, 0],
+	[1962538549, 1, 0, -1, 0],
+	[3816091942, 3, 2, -1, 0],
+	[4130837190, 0, 10, -1, 0],
+	[1861568052, 0, 1, -1, 0],
+	[2290910058, 6, 2, -1, 0],
+	[1578940118, 1, 1, -1, 0],
+	[1571676964, 0, 1, -1, 2],
+	[3640172371, 0, 2, -1, 2],
+	[1658164312, 2, 1, -1, 0],
+	[98883956, 1, 1, -1, 0],
+	[3114091169, 0, 1, -1, 0],
+	[2570684145, 4, 1, -1, 2],
+	[4007615411, 0, 1, -1, 0],
+	[3665310159, 2, 1, -1, 1],
+	[852550504, 3, 1, -1, 0],
+	[2333572067, 0, 1, -1, 0],
+	[935994771, 1, 1, -1, 0],
+	[1127795596, 1, 1, -1, 0],
+	[4168223991, 0, 1, -1, 0],
+	[18585280, 0, 1, -1, 1],
+	[327482016, 0, 1, -1, 2],
+	[3458098201, 7, 1, -1, 0],
+	[478613943, 2, 1, -1, 1],
+	[2792197902, 0, 1, -1, 2],
+	[284670956, 0, 1, -1, 0],
+	[2099185390, 0, 1, -1, 0],
+	[1202202685, 0, 1, -1, 0],
+	[2122174751, 0, 1, -1, 0],
+	[3633864632, 0, 1, -1, 0],
+	[3103053065, 0, 1, -1, 0],
+	[820624960, 0, 1, -1, 0],
+	[1134479292, 0, 1, -1, 0],
+	[2511257455, 3, 1, -1, 3],
+	[2599708267, 0, 1, -1, 0],
+	[613180822, 1, 1, -1, 0],
+	[2885186814, 0, 1, -1, 0],
+	[221503477, 0, 1, -1, 0],
+	[1054317075, 0, 1, -1, 3],
+	[683872522, 0, 1, -1, 1],
+	[1739278764, 0, 2, -1, 0],
+	[2855249023, 0, 1, -1, 0],
+	[3721841948, 0, 1, -1, 0],
+	[1285203515, 0, 1, -1, 0],
+	[1365487849, 6, 1, -1, 0],
+	[955229746, 0, 1, -1, 0],
+	[3128009767, 0, 10, -1, 0],
+	[441885003, 0, 1, -1, 0],
+	[3433971238, 0, 1, -1, 2],
+	[1038765354, 3, 1, -1, 0],
+	[1174347196, 0, 1, -1, 0],
+	[3649806352, 1, 1, -1, 0],
+	[2973729510, 2, 1, -1, 0],
+	[2571931329, 1, 6, -1, 0],
+	[3884442008, 0, 1, -1, 0],
+	[978673395, 1, 1, -1, 0],
+	[4050927174, 0, 1, -1, 0],
+	[1260103069, 0, 1, -1, 0],
+	[4168894280, 0, 1, -1, 0],
+	[4045587091, 0, 1, -1, 0],
+	[2003494159, 1, 1, -1, 0],
+	[51193042, 0, 1, -1, 0],
+	[2634540382, 3, 1, -1, 0],
+	[886364171, 0, 1, -1, 0],
+	[3898604944, 0, 1, -1, 0],
+	[3388129398, 0, 1, -1, 0],
+	[3964382884, 2, 1, -1, 1],
+	[3305874255, 0, 1, -1, 0],
+	[156590431, 0, 1, -1, 0],
+	[3106485751, 0, 0, -1, 0],
+	[3035674767, 0, 1, -1, 0],
+	[851697110, 0, 1, -1, 0]
+]
diff --git a/gateway/src/opcodes/index.ts b/gateway/src/opcodes/index.ts
new file mode 100644
index 00000000..fa57f568
--- /dev/null
+++ b/gateway/src/opcodes/index.ts
@@ -0,0 +1,25 @@
+import { Payload } from "../util/Constants";
+import WebSocket from "../util/WebSocket";
+import { onHeartbeat } from "./Heartbeat";
+import { onIdentify } from "./Identify";
+import { onLazyRequest } from "./LazyRequest";
+import { onPresenceUpdate } from "./PresenceUpdate";
+import { onRequestGuildMembers } from "./RequestGuildMembers";
+import { onResume } from "./Resume";
+import { onVoiceStateUpdate } from "./VoiceStateUpdate";
+
+export type OPCodeHandler = (this: WebSocket, data: Payload) => any;
+
+export default {
+	1: onHeartbeat,
+	2: onIdentify,
+	3: onPresenceUpdate,
+	4: onVoiceStateUpdate,
+	// 5: Voice Server Ping
+	6: onResume,
+	// 7: Reconnect: You should attempt to reconnect and resume immediately.
+	8: onRequestGuildMembers,
+	// 9: Invalid Session
+	// 10: Hello
+	14: onLazyRequest,
+};
diff --git a/gateway/src/opcodes/instanceOf.ts b/gateway/src/opcodes/instanceOf.ts
new file mode 100644
index 00000000..c4ee5ee6
--- /dev/null
+++ b/gateway/src/opcodes/instanceOf.ts
@@ -0,0 +1,18 @@
+import { instanceOf } from "lambert-server";
+import { CLOSECODES } from "../util/Constants";
+import WebSocket from "../util/WebSocket";
+
+export function check(this: WebSocket, schema: any, data: any) {
+	try {
+		const error = instanceOf(schema, data, { path: "body" });
+		if (error !== true) {
+			throw error;
+		}
+		return true;
+	} catch (error) {
+		console.error(error);
+		// invalid payload
+		this.close(CLOSECODES.Decode_error);
+		throw error;
+	}
+}
diff --git a/gateway/src/schema/Activity.ts b/gateway/src/schema/Activity.ts
new file mode 100644
index 00000000..62cf7ad6
--- /dev/null
+++ b/gateway/src/schema/Activity.ts
@@ -0,0 +1,49 @@
+import { ActivityBodySchema } from "@fosscord/server-util";
+import { EmojiSchema } from "./Emoji";
+
+export const ActivitySchema = {
+	afk: Boolean,
+	status: String,
+	$activities: [ActivityBodySchema],
+	$since: Number, // unix time (in milliseconds) of when the client went idle, or null if the client is not idle
+};
+
+export interface ActivitySchema {
+	afk: boolean;
+	status: string;
+	activities?: [
+		{
+			name: string; // the activity's name
+			type: number; // activity type // TODO: check if its between range 0-5
+			url?: string; // stream url, is validated when type is 1
+			created_at?: number; // unix timestamp of when the activity was added to the user's session
+			timestamps?: {
+				// unix timestamps for start and/or end of the game
+				start: number;
+				end: number;
+			};
+			application_id?: string; // application id for the game
+			details?: string;
+			state?: string;
+			emoji?: EmojiSchema;
+			party?: {
+				id?: string;
+				size?: [number]; // used to show the party's current and maximum size // TODO: array length 2
+			};
+			assets?: {
+				large_image?: string; // the id for a large asset of the activity, usually a snowflake
+				large_text?: string; // text displayed when hovering over the large image of the activity
+				small_image?: string; // the id for a small asset of the activity, usually a snowflake
+				small_text?: string; // text displayed when hovering over the small image of the activity
+			};
+			secrets?: {
+				join?: string; // the secret for joining a party
+				spectate?: string; // the secret for spectating a game
+				match?: string; // the secret for a specific instanced match
+			};
+			instance?: boolean;
+			flags: bigint; // activity flags OR d together, describes what the payload includes
+		}
+	];
+	since?: number; // unix time (in milliseconds) of when the client went idle, or null if the client is not idle
+}
diff --git a/gateway/src/schema/Emoji.ts b/gateway/src/schema/Emoji.ts
new file mode 100644
index 00000000..413b8359
--- /dev/null
+++ b/gateway/src/schema/Emoji.ts
@@ -0,0 +1,11 @@
+export const EmojiSchema = {
+	name: String, // the name of the emoji
+	$id: String, // the id of the emoji
+	animated: Boolean, // whether this emoji is animated
+};
+
+export interface EmojiSchema {
+	name: string;
+	id?: string;
+	animated: Boolean;
+}
diff --git a/gateway/src/schema/Identify.ts b/gateway/src/schema/Identify.ts
new file mode 100644
index 00000000..646c5f05
--- /dev/null
+++ b/gateway/src/schema/Identify.ts
@@ -0,0 +1,83 @@
+import { ActivitySchema } from "./Activity";
+
+export const IdentifySchema = {
+	token: String,
+	$intents: BigInt, // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
+	$properties: {
+		// bruh discord really uses $ in the property key for bots, so we need to double prefix it, because instanceOf treats $ (prefix) as a optional key
+		$os: String,
+		$os_arch: String,
+		$browser: String,
+		$device: String,
+		$$os: String,
+		$$browser: String,
+		$$device: String,
+		$browser_user_agent: String,
+		$browser_version: String,
+		$os_version: String,
+		$referrer: String,
+		$$referrer: String,
+		$referring_domain: String,
+		$$referring_domain: String,
+		$referrer_current: String,
+		$referring_domain_current: String,
+		$release_channel: String,
+		$client_build_number: Number,
+		$client_event_source: String,
+		$client_version: String,
+		$system_locale: String,
+	},
+	$presence: ActivitySchema,
+	$compress: Boolean,
+	$large_threshold: Number,
+	$shard: [BigInt, BigInt],
+	$guild_subscriptions: Boolean,
+	$capabilities: Number,
+	$client_state: {
+		$guild_hashes: Object,
+		$highest_last_message_id: String,
+		$read_state_version: Number,
+		$user_guild_settings_version: Number,
+	},
+	$v: Number,
+};
+
+export interface IdentifySchema {
+	token: string;
+	properties: {
+		// bruh discord really uses $ in the property key, so we need to double prefix it, because instanceOf treats $ (prefix) as a optional key
+		os?: string;
+		os_atch?: string;
+		browser?: string;
+		device?: string;
+		$os?: string;
+		$browser?: string;
+		$device?: string;
+		browser_user_agent?: string;
+		browser_version?: string;
+		os_version?: string;
+		referrer?: string;
+		referring_domain?: string;
+		referrer_current?: string;
+		referring_domain_current?: string;
+		release_channel?: "stable" | "dev" | "ptb" | "canary";
+		client_build_number?: number;
+		client_event_source?: any;
+		client_version?: string;
+		system_locale?: string;
+	};
+	intents?: bigint; // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
+	presence?: ActivitySchema;
+	compress?: boolean;
+	large_threshold?: number;
+	shard?: [bigint, bigint];
+	guild_subscriptions?: boolean;
+	capabilities?: number;
+	client_state?: {
+		guild_hashes?: any;
+		highest_last_message_id?: string;
+		read_state_version?: number;
+		user_guild_settings_version?: number;
+	};
+	v?: number;
+}
diff --git a/gateway/src/schema/LazyRequest.ts b/gateway/src/schema/LazyRequest.ts
new file mode 100644
index 00000000..7c828ac6
--- /dev/null
+++ b/gateway/src/schema/LazyRequest.ts
@@ -0,0 +1,19 @@
+export interface LazyRequest {
+	guild_id: string;
+	channels?: Record<string, [number, number]>;
+	activities?: boolean;
+	threads?: boolean;
+	typing?: true;
+	members?: any[];
+	thread_member_lists?: any[];
+}
+
+export const LazyRequest = {
+	guild_id: String,
+	$activities: Boolean,
+	$channels: Object,
+	$typing: Boolean,
+	$threads: Boolean,
+	$members: [] as any[],
+	$thread_member_lists: [] as any[],
+};
diff --git a/gateway/src/schema/VoiceStateUpdate.ts.ts b/gateway/src/schema/VoiceStateUpdate.ts.ts
new file mode 100644
index 00000000..4345c2f6
--- /dev/null
+++ b/gateway/src/schema/VoiceStateUpdate.ts.ts
@@ -0,0 +1,15 @@
+export const VoiceStateUpdateSchema = {
+	$guild_id: String,
+	channel_id: String,
+	self_mute: Boolean,
+	self_deaf: Boolean,
+	self_video: Boolean,
+};
+
+export interface VoiceStateUpdateSchema {
+	guild_id?: string;
+	channel_id: string;
+	self_mute: boolean;
+	self_deaf: boolean;
+	self_video: boolean;
+}
diff --git a/gateway/src/start.ts b/gateway/src/start.ts
new file mode 100644
index 00000000..09a54751
--- /dev/null
+++ b/gateway/src/start.ts
@@ -0,0 +1,14 @@
+process.on("uncaughtException", console.error);
+process.on("unhandledRejection", console.error);
+
+import { Server } from "./Server";
+import { config } from "dotenv";
+config();
+
+var port = Number(process.env.PORT);
+if (isNaN(port)) port = 3002;
+
+const server = new Server({
+	port,
+});
+server.start();
diff --git a/gateway/src/util/Config.ts b/gateway/src/util/Config.ts
new file mode 100644
index 00000000..9ceb8cd5
--- /dev/null
+++ b/gateway/src/util/Config.ts
@@ -0,0 +1,41 @@
+// @ts-nocheck
+import { Config } from "@fosscord/server-util";
+import { getConfigPathForFile } from "@fosscord/server-util/dist/util/Config";
+import Ajv, { JSONSchemaType } from "ajv";
+
+export interface DefaultOptions {
+	endpoint?: string;
+	security: {
+		jwtSecret: string;
+	};
+}
+
+const schema: JSONSchemaType<DefaultOptions> = {
+	type: "object",
+	properties: {
+		endpoint: {
+			type: "string",
+			nullable: true,
+		},
+		security: {
+			type: "object",
+			properties: {
+				jwtSecret: {
+					type: "string",
+				},
+			},
+			required: ["jwtSecret"],
+		},
+	},
+	required: ["security"],
+};
+
+const ajv = new Ajv();
+const validator = ajv.compile(schema);
+
+const configPath = getConfigPathForFile("fosscord", "gateway", ".json");
+export const gatewayConfig = new Config<DefaultOptions>({
+	path: configPath,
+	schemaValidator: validator,
+	schema: schema,
+});
diff --git a/gateway/src/util/Constants.ts b/gateway/src/util/Constants.ts
new file mode 100644
index 00000000..692f9028
--- /dev/null
+++ b/gateway/src/util/Constants.ts
@@ -0,0 +1,50 @@
+export enum OPCODES {
+	Dispatch = 0,
+	Heartbeat = 1,
+	Identify = 2,
+	Presence_Update = 3,
+	Voice_State_Update = 4,
+	Voice_Server_Ping = 5, // ? What is opcode 5?
+	Resume = 6,
+	Reconnect = 7,
+	Request_Guild_Members = 8,
+	Invalid_Session = 9,
+	Hello = 10,
+	Heartbeat_ACK = 11,
+	Guild_Sync = 12,
+	DM_Update = 13,
+	Lazy_Request = 14,
+	Lobby_Connect = 15,
+	Lobby_Disconnect = 16,
+	Lobby_Voice_States_Update = 17,
+	Stream_Create = 18,
+	Stream_Delete = 19,
+	Stream_Watch = 20,
+	Stream_Ping = 21,
+	Stream_Set_Paused = 22,
+	Request_Application_Commands = 24,
+}
+export enum CLOSECODES {
+	Unknown_error = 4000,
+	Unknown_opcode,
+	Decode_error,
+	Not_authenticated,
+	Authentication_failed,
+	Already_authenticated,
+	Invalid_session,
+	Invalid_seq,
+	Rate_limited,
+	Session_timed_out,
+	Invalid_shard,
+	Sharding_required,
+	Invalid_API_version,
+	Invalid_intent,
+	Disallowed_intent,
+}
+
+export interface Payload {
+	op: OPCODES;
+	d?: any;
+	s?: number;
+	t?: string;
+}
diff --git a/gateway/src/util/Send.ts b/gateway/src/util/Send.ts
new file mode 100644
index 00000000..be25ac4f
--- /dev/null
+++ b/gateway/src/util/Send.ts
@@ -0,0 +1,28 @@
+var erlpack: any;
+try {
+	erlpack = require("erlpack");
+} catch (error) {}
+import { Payload } from "../util/Constants";
+
+import WebSocket from "./WebSocket";
+
+export async function Send(socket: WebSocket, data: Payload) {
+	let buffer: Buffer | string;
+	if (socket.encoding === "etf") buffer = erlpack.pack(data);
+	// TODO: encode circular object
+	else if (socket.encoding === "json") buffer = JSON.stringify(data);
+	else return;
+	// TODO: compression
+	if (socket.deflate) {
+		socket.deflate.write(buffer);
+		socket.deflate.flush();
+		return;
+	}
+
+	return new Promise((res, rej) => {
+		socket.send(buffer, (err) => {
+			if (err) return rej(err);
+			return res(null);
+		});
+	});
+}
diff --git a/gateway/src/util/WebSocket.ts b/gateway/src/util/WebSocket.ts
new file mode 100644
index 00000000..1bd0ff2f
--- /dev/null
+++ b/gateway/src/util/WebSocket.ts
@@ -0,0 +1,23 @@
+import { Intents, Permissions } from "@fosscord/server-util";
+import WS, { Server, Data } from "ws";
+import { Deflate } from "zlib";
+import { Channel } from "amqplib";
+
+interface WebSocket extends WS {
+	version: number;
+	user_id: string;
+	encoding: "etf" | "json";
+	compress?: "zlib-stream";
+	shard_count?: bigint;
+	shard_id?: bigint;
+	deflate?: Deflate;
+	heartbeatTimeout: NodeJS.Timeout;
+	readyTimeout: NodeJS.Timeout;
+	intents: Intents;
+	sequence: number;
+	rabbitCh?: Channel & { queues: Record<string, string> };
+	permissions: Record<string, Permissions>;
+}
+
+export default WebSocket;
+export { Server, Data };
diff --git a/gateway/src/util/setHeartbeat.ts b/gateway/src/util/setHeartbeat.ts
new file mode 100644
index 00000000..9f88b481
--- /dev/null
+++ b/gateway/src/util/setHeartbeat.ts
@@ -0,0 +1,11 @@
+import { CLOSECODES } from "./Constants";
+import WebSocket from "./WebSocket";
+
+// TODO: make heartbeat timeout configurable
+export function setHeartbeat(socket: WebSocket) {
+	if (socket.heartbeatTimeout) clearTimeout(socket.heartbeatTimeout);
+
+	socket.heartbeatTimeout = setTimeout(() => {
+		return socket.close(CLOSECODES.Session_timed_out);
+	}, 1000 * 45);
+}
diff --git a/gateway/tsconfig.json b/gateway/tsconfig.json
new file mode 100644
index 00000000..e5bf92c6
--- /dev/null
+++ b/gateway/tsconfig.json
@@ -0,0 +1,72 @@
+{
+	"include": ["src/**/*.ts"],
+	"exclude": ["*.js", "dist", "attachments"],
+	"compilerOptions": {
+		/* Visit https://aka.ms/tsconfig.json to read more about this file */
+
+		/* Basic Options */
+		// "incremental": true,                   /* Enable incremental compilation */
+		"target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
+		"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
+		"lib": ["ES2015", "ES2020.BigInt", "DOM"] /* Specify library files to be included in the compilation. */,
+		"allowJs": true /* Allow javascript files to be compiled. */,
+		"checkJs": true /* Report errors in .js files. */,
+		// "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+		"declaration": true /* Generates corresponding '.d.ts' file. */,
+		"declarationMap": false /* Generates a sourcemap for each corresponding '.d.ts' file. */,
+		// "sourceMap": true /* Generates corresponding '.map' file. */,
+		// "outFile": "./",                       /* Concatenate and emit output to single file. */
+		"outDir": "./dist/" /* Redirect output structure to the directory. */,
+		"rootDir": "./src/" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
+		// "composite": true,                     /* Enable project compilation */
+		// "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
+		// "removeComments": true,                /* Do not emit comments to output. */
+		// "noEmit": true,                        /* Do not emit outputs. */
+		// "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
+		// "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+		// "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+		/* Strict Type-Checking Options */
+		"strict": false /* Enable all strict type-checking options. */,
+		"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
+		"strictNullChecks": true /* Enable strict null checks. */,
+		// "strictFunctionTypes": true,           /* Enable strict checking of function types. */
+		// "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+		"strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */,
+		// "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
+		"alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
+
+		/* Additional Checks */
+		// "noUnusedLocals": true,                /* Report errors on unused locals. */
+		// "noUnusedParameters": true,            /* Report errors on unused parameters. */
+		// "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
+		// "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */
+
+		/* Module Resolution Options */
+		// "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
+		// "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
+		// "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
+		// "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
+		// "typeRoots": [],                       /* List of folders to include type definitions from. */
+		"types": ["node"] /* Type declaration files to be included in compilation. */,
+		// "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+		"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
+		// "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
+		// "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */
+
+		/* Source Map Options */
+		// "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+		// "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
+		"inlineSourceMap": true /* Emit a single file with source maps instead of having a separate file. */,
+		// "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+		/* Experimental Options */
+		// "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
+		// "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
+
+		/* Advanced Options */
+		"skipLibCheck": true /* Skip type checking of declaration files. */,
+		"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
+		"resolveJsonModule": true
+	}
+}