From 87a42229d7848f21d6ed7319f4bc5a9c6d3ceff1 Mon Sep 17 00:00:00 2001
From: Thijn <thijnkroon@gmail.com>
Date: Thu, 7 Nov 2024 11:42:57 +0100
Subject: [PATCH 1/6] feat: convert to deno

---
 .eslintrc.json                             |   38 -
 .github/workflows/build.yml                |   44 -
 .github/workflows/check.yml                |   26 +
 .github/workflows/format.yml               |   44 -
 .gitignore                                 |    9 +-
 .prettierignore                            |    2 -
 .prettierrc.json                           |    7 -
 deno.json                                  |   34 +
 deno.lock                                  |  149 +
 nodemon.json                               |   12 -
 package-lock.json                          | 3747 --------------------
 package.json                               |   34 -
 src/client/index.ts                        |    9 +-
 src/commands/debug/index.ts                |    6 +-
 src/commands/debug/ping.ts                 |   16 +-
 src/commands/general/help.ts               |   16 +-
 src/commands/general/index.ts              |   12 +-
 src/commands/general/info.ts               |   93 +-
 src/commands/index.ts                      |    4 +-
 src/constants/index.ts                     |    2 -
 src/constants/namespaces.ts                |    4 -
 src/constants/style.ts                     |   13 -
 src/env.ts                                 |   17 +-
 src/events/index.ts                        |    4 +-
 src/events/interactionCreate/commands.ts   |   22 +-
 src/events/interactionCreate/help.ts       |    5 +-
 src/events/interactionCreate/index.ts      |    6 +-
 src/events/interactionCreate/pagination.ts |    5 +-
 src/events/ready.ts                        |    4 +-
 src/index.ts                               |    7 +-
 src/scripts/clear.ts                       |   13 +-
 src/scripts/deploy.ts                      |   23 +-
 src/types/commands.ts                      |    8 +-
 src/types/context.ts                       |    4 +-
 src/types/events.ts                        |    4 +-
 src/types/index.ts                         |    6 +-
 src/types/pagination.ts                    |    4 +-
 src/utils/command.ts                       |    2 +-
 src/utils/constants.ts                     |   18 +
 src/utils/event.ts                         |   11 +-
 src/utils/help.ts                          |   26 +-
 src/utils/index.ts                         |   23 +-
 src/utils/pagination.ts                    |   33 +-
 src/utils/paginators/help.ts               |   36 +-
 src/utils/paginators/index.ts              |   18 +-
 src/utils/replies.ts                       |   32 +-
 src/utils/split.ts                         |   10 +-
 tsconfig.json                              |   21 -
 48 files changed, 474 insertions(+), 4209 deletions(-)
 delete mode 100644 .eslintrc.json
 delete mode 100644 .github/workflows/build.yml
 create mode 100644 .github/workflows/check.yml
 delete mode 100644 .github/workflows/format.yml
 delete mode 100644 .prettierignore
 delete mode 100644 .prettierrc.json
 create mode 100644 deno.json
 create mode 100644 deno.lock
 delete mode 100644 nodemon.json
 delete mode 100644 package-lock.json
 delete mode 100644 package.json
 delete mode 100644 src/constants/index.ts
 delete mode 100644 src/constants/namespaces.ts
 delete mode 100644 src/constants/style.ts
 create mode 100644 src/utils/constants.ts
 delete mode 100644 tsconfig.json

diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index 8e23169..0000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-  "env": {
-    "browser": true,
-    "es2021": true
-  },
-  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
-  "overrides": [
-    {
-      "env": {
-        "node": true
-      },
-      "files": [".eslintrc.{js,cjs}"],
-      "parserOptions": {
-        "sourceType": "script"
-      }
-    }
-  ],
-  "parser": "@typescript-eslint/parser",
-  "parserOptions": {
-    "ecmaVersion": "latest",
-    "sourceType": "module"
-  },
-  "plugins": ["@typescript-eslint"],
-  "rules": {
-    "no-unused-vars": "off",
-    "@typescript-eslint/no-unused-vars": [
-      "warn",
-      {
-        "vars": "all",
-        "varsIgnorePattern": "^_",
-        "args": "after-used",
-        "argsIgnorePattern": "^_"
-      }
-    ],
-    "@typescript-eslint/no-explicit-any": "off",
-    "@typescript-eslint/no-empty-interface": "off"
-  }
-}
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index 436a97f..0000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: Build Check
-
-on:
-  workflow_dispatch:
-  push:
-    branches: ['main']
-  pull_request:
-    branches: ['main']
-
-jobs:
-  # Install and cache npm dependencies
-  install-cache:
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout Commit
-        uses: actions/checkout@v3
-      - name: Cache node modules
-        uses: actions/cache@v3
-        id: npm-cache
-        with:
-          path: |
-            **/node_modules
-          key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
-          restore-keys: |
-            ${{ runner.os }}-build
-      - name: Install dependencies if cache invalid
-        if: steps.npm-cache.outputs.cache-hit != 'true'
-        run: npm ci
-  build:
-    runs-on: ubuntu-latest
-    needs: install-cache
-    steps:
-      - uses: actions/checkout@v3
-      - name: Restore npm cache
-        uses: actions/cache@v3
-        id: npm-cache
-        with:
-          path: |
-            **/node_modules
-          key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
-          restore-keys: |
-            ${{ runner.os }}-build
-      - name: Run build
-        run: npm run build
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
new file mode 100644
index 0000000..48ce076
--- /dev/null
+++ b/.github/workflows/check.yml
@@ -0,0 +1,26 @@
+name: Check
+
+on:
+  workflow_dispatch:
+  push:
+    branches: ["main"]
+  pull_request:
+    branches: ["main"]
+
+jobs:
+  type-check:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: denoland/setup-deno@v2
+        with:
+          deno-version: v2.x
+      - run: deno task check
+  format-check:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: denoland/setup-deno@v2
+        with:
+          deno-version: v2.x
+      - run: deno fmt --check
diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml
deleted file mode 100644
index 106510e..0000000
--- a/.github/workflows/format.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: Format Check
-
-on:
-  workflow_dispatch:
-  push:
-    branches: ['main']
-  pull_request:
-    branches: ['main']
-
-jobs:
-  # Install and cache npm dependencies
-  install-cache:
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout Commit
-        uses: actions/checkout@v3
-      - name: Cache node modules
-        uses: actions/cache@v3
-        id: npm-cache
-        with:
-          path: |
-            **/node_modules
-          key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
-          restore-keys: |
-            ${{ runner.os }}-build
-      - name: Install dependencies if cache invalid
-        if: steps.npm-cache.outputs.cache-hit != 'true'
-        run: npm ci
-  format-check:
-    runs-on: ubuntu-latest
-    needs: install-cache
-    steps:
-      - uses: actions/checkout@v3
-      - name: Restore npm cache
-        uses: actions/cache@v3
-        id: npm-cache
-        with:
-          path: |
-            **/node_modules
-          key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
-          restore-keys: |
-            ${{ runner.os }}-build
-      - name: Run Prettier formatting check
-        run: npx prettier --check ./src
diff --git a/.gitignore b/.gitignore
index f94630c..7889494 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
-node_modules/
-dist/
-.env
\ No newline at end of file
+.env
+
+/.vs/
+/.vscode/
+/node_modules/
+/dist/
diff --git a/.prettierignore b/.prettierignore
deleted file mode 100644
index db4c6d9..0000000
--- a/.prettierignore
+++ /dev/null
@@ -1,2 +0,0 @@
-dist
-node_modules
\ No newline at end of file
diff --git a/.prettierrc.json b/.prettierrc.json
deleted file mode 100644
index dbf0f21..0000000
--- a/.prettierrc.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "endOfLine": "auto",
-  "semi": true,
-  "singleQuote": true,
-  "tabWidth": 2,
-  "trailingComma": "es5"
-}
diff --git a/deno.json b/deno.json
new file mode 100644
index 0000000..1a05525
--- /dev/null
+++ b/deno.json
@@ -0,0 +1,34 @@
+{
+  "tasks": {
+    "dev": "deno run --watch --env-file --allow-net --allow-read src/index.ts",
+    "check": "deno check src/index.ts",
+    "lint": "deno lint --fix",
+    "fmt": "deno fmt",
+    "fmt:check": "deno fmt --check",
+    "deploy": "deno run --env-file --allow-net --allow-read src/scripts/deploy.ts",
+    "clear": "deno run --env-file --allow-net --allow-read src/scripts/clear.ts"
+  },
+  "lint": {
+    "include": ["src/"],
+    "rules": {
+      "tags": ["recommended"]
+    }
+  },
+  "fmt": {
+    "lineWidth": 80,
+    "indentWidth": 2,
+    "semiColons": true,
+    "singleQuote": true,
+    "include": ["src/"]
+  },
+  "exclude": ["node_modules/", "dist/"],
+  "imports": {
+    "env": "./src/env.ts",
+    "client": "./src/client/index.ts",
+    "commands": "./src/commands/index.ts",
+    "types": "./src/types/index.ts",
+    "utils": "./src/utils/index.ts",
+    "discord.js": "npm:discord.js@^14.16.3"
+  },
+  "nodeModulesDir": "auto"
+}
diff --git a/deno.lock b/deno.lock
new file mode 100644
index 0000000..6e5575f
--- /dev/null
+++ b/deno.lock
@@ -0,0 +1,149 @@
+{
+  "version": "4",
+  "specifiers": {
+    "npm:discord.js@^14.16.3": "14.16.3"
+  },
+  "npm": {
+    "@discordjs/builders@1.9.0": {
+      "integrity": "sha512-0zx8DePNVvQibh5ly5kCEei5wtPBIUbSoE9n+91Rlladz4tgtFbJ36PZMxxZrTEOQ7AHMZ/b0crT/0fCy6FTKg==",
+      "dependencies": [
+        "@discordjs/formatters",
+        "@discordjs/util",
+        "@sapphire/shapeshift",
+        "discord-api-types@0.37.97",
+        "fast-deep-equal",
+        "ts-mixer",
+        "tslib"
+      ]
+    },
+    "@discordjs/collection@1.5.3": {
+      "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ=="
+    },
+    "@discordjs/collection@2.1.1": {
+      "integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="
+    },
+    "@discordjs/formatters@0.5.0": {
+      "integrity": "sha512-98b3i+Y19RFq1Xke4NkVY46x8KjJQjldHUuEbCqMvp1F5Iq9HgnGpu91jOi/Ufazhty32eRsKnnzS8n4c+L93g==",
+      "dependencies": [
+        "discord-api-types@0.37.97"
+      ]
+    },
+    "@discordjs/rest@2.4.0": {
+      "integrity": "sha512-Xb2irDqNcq+O8F0/k/NaDp7+t091p+acb51iA4bCKfIn+WFWd6HrNvcsSbMMxIR9NjcMZS6NReTKygqiQN+ntw==",
+      "dependencies": [
+        "@discordjs/collection@2.1.1",
+        "@discordjs/util",
+        "@sapphire/async-queue",
+        "@sapphire/snowflake",
+        "@vladfrangu/async_event_emitter",
+        "discord-api-types@0.37.97",
+        "magic-bytes.js",
+        "tslib",
+        "undici"
+      ]
+    },
+    "@discordjs/util@1.1.1": {
+      "integrity": "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g=="
+    },
+    "@discordjs/ws@1.1.1": {
+      "integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==",
+      "dependencies": [
+        "@discordjs/collection@2.1.1",
+        "@discordjs/rest",
+        "@discordjs/util",
+        "@sapphire/async-queue",
+        "@types/ws",
+        "@vladfrangu/async_event_emitter",
+        "discord-api-types@0.37.83",
+        "tslib",
+        "ws"
+      ]
+    },
+    "@sapphire/async-queue@1.5.4": {
+      "integrity": "sha512-id65RxAx34DCk8KAVTPWwcephJSkStiS9M15F87+zvK2gK47wf7yeRIo8WiuKeXQS6bsyo/uQ/t0QW1cLmSb+A=="
+    },
+    "@sapphire/shapeshift@4.0.0": {
+      "integrity": "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==",
+      "dependencies": [
+        "fast-deep-equal",
+        "lodash"
+      ]
+    },
+    "@sapphire/snowflake@3.5.3": {
+      "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ=="
+    },
+    "@types/node@22.5.4": {
+      "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
+      "dependencies": [
+        "undici-types"
+      ]
+    },
+    "@types/ws@8.5.13": {
+      "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==",
+      "dependencies": [
+        "@types/node"
+      ]
+    },
+    "@vladfrangu/async_event_emitter@2.4.6": {
+      "integrity": "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA=="
+    },
+    "discord-api-types@0.37.100": {
+      "integrity": "sha512-a8zvUI0GYYwDtScfRd/TtaNBDTXwP5DiDVX7K5OmE+DRT57gBqKnwtOC5Ol8z0mRW8KQfETIgiB8U0YZ9NXiCA=="
+    },
+    "discord-api-types@0.37.83": {
+      "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA=="
+    },
+    "discord-api-types@0.37.97": {
+      "integrity": "sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA=="
+    },
+    "discord.js@14.16.3": {
+      "integrity": "sha512-EPCWE9OkA9DnFFNrO7Kl1WHHDYFXu3CNVFJg63bfU7hVtjZGyhShwZtSBImINQRWxWP2tgo2XI+QhdXx28r0aA==",
+      "dependencies": [
+        "@discordjs/builders",
+        "@discordjs/collection@1.5.3",
+        "@discordjs/formatters",
+        "@discordjs/rest",
+        "@discordjs/util",
+        "@discordjs/ws",
+        "@sapphire/snowflake",
+        "discord-api-types@0.37.100",
+        "fast-deep-equal",
+        "lodash.snakecase",
+        "tslib",
+        "undici"
+      ]
+    },
+    "fast-deep-equal@3.1.3": {
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+    },
+    "lodash.snakecase@4.1.1": {
+      "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
+    },
+    "lodash@4.17.21": {
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
+    "magic-bytes.js@1.10.0": {
+      "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ=="
+    },
+    "ts-mixer@6.0.4": {
+      "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="
+    },
+    "tslib@2.8.1": {
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+    },
+    "undici-types@6.19.8": {
+      "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
+    },
+    "undici@6.19.8": {
+      "integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g=="
+    },
+    "ws@8.18.0": {
+      "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="
+    }
+  },
+  "workspace": {
+    "dependencies": [
+      "npm:discord.js@^14.16.3"
+    ]
+  }
+}
diff --git a/nodemon.json b/nodemon.json
deleted file mode 100644
index 1f316f7..0000000
--- a/nodemon.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "restartable": "rs",
-  "ignore": ["node_modules/"],
-  "watch": ["src/"],
-  "execMap": {
-    "ts": "node -r ts-node/register"
-  },
-  "env": {
-    "NODE_ENV": "development"
-  },
-  "ext": "js,json,ts"
-}
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index 83cb157..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,3747 +0,0 @@
-{
-  "name": "discord-bot-template",
-  "version": "1.0.0",
-  "lockfileVersion": 2,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "discord-bot-template",
-      "version": "1.0.0",
-      "license": "MIT",
-      "dependencies": {
-        "cross-env": "^7.0.3",
-        "discord.js": "^14.15.3",
-        "dotenv": "^16.4.5"
-      },
-      "devDependencies": {
-        "@types/node": "^20.14.10",
-        "@typescript-eslint/eslint-plugin": "^7.16.0",
-        "@typescript-eslint/parser": "^7.16.0",
-        "eslint": "^8.56.0",
-        "nodemon": "^3.1.4",
-        "prettier": "^3.3.2",
-        "ts-node": "^10.9.2",
-        "typescript": "^5.5.3"
-      }
-    },
-    "node_modules/@aashutoshrathi/word-wrap": {
-      "version": "1.2.6",
-      "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
-      "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/@cspotcode/source-map-support": {
-      "version": "0.8.1",
-      "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
-      "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
-      "dev": true,
-      "dependencies": {
-        "@jridgewell/trace-mapping": "0.3.9"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@discordjs/builders": {
-      "version": "1.8.2",
-      "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.8.2.tgz",
-      "integrity": "sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==",
-      "dependencies": {
-        "@discordjs/formatters": "^0.4.0",
-        "@discordjs/util": "^1.1.0",
-        "@sapphire/shapeshift": "^3.9.7",
-        "discord-api-types": "0.37.83",
-        "fast-deep-equal": "^3.1.3",
-        "ts-mixer": "^6.0.4",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.11.0"
-      },
-      "funding": {
-        "url": "https://github.com/discordjs/discord.js?sponsor"
-      }
-    },
-    "node_modules/@discordjs/collection": {
-      "version": "1.5.3",
-      "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz",
-      "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==",
-      "engines": {
-        "node": ">=16.11.0"
-      }
-    },
-    "node_modules/@discordjs/formatters": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.4.0.tgz",
-      "integrity": "sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==",
-      "dependencies": {
-        "discord-api-types": "0.37.83"
-      },
-      "engines": {
-        "node": ">=16.11.0"
-      },
-      "funding": {
-        "url": "https://github.com/discordjs/discord.js?sponsor"
-      }
-    },
-    "node_modules/@discordjs/rest": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.3.0.tgz",
-      "integrity": "sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==",
-      "dependencies": {
-        "@discordjs/collection": "^2.1.0",
-        "@discordjs/util": "^1.1.0",
-        "@sapphire/async-queue": "^1.5.2",
-        "@sapphire/snowflake": "^3.5.3",
-        "@vladfrangu/async_event_emitter": "^2.2.4",
-        "discord-api-types": "0.37.83",
-        "magic-bytes.js": "^1.10.0",
-        "tslib": "^2.6.2",
-        "undici": "6.13.0"
-      },
-      "engines": {
-        "node": ">=16.11.0"
-      },
-      "funding": {
-        "url": "https://github.com/discordjs/discord.js?sponsor"
-      }
-    },
-    "node_modules/@discordjs/rest/node_modules/@discordjs/collection": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz",
-      "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==",
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/discordjs/discord.js?sponsor"
-      }
-    },
-    "node_modules/@discordjs/util": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.0.tgz",
-      "integrity": "sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==",
-      "engines": {
-        "node": ">=16.11.0"
-      },
-      "funding": {
-        "url": "https://github.com/discordjs/discord.js?sponsor"
-      }
-    },
-    "node_modules/@discordjs/ws": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.1.tgz",
-      "integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==",
-      "dependencies": {
-        "@discordjs/collection": "^2.1.0",
-        "@discordjs/rest": "^2.3.0",
-        "@discordjs/util": "^1.1.0",
-        "@sapphire/async-queue": "^1.5.2",
-        "@types/ws": "^8.5.10",
-        "@vladfrangu/async_event_emitter": "^2.2.4",
-        "discord-api-types": "0.37.83",
-        "tslib": "^2.6.2",
-        "ws": "^8.16.0"
-      },
-      "engines": {
-        "node": ">=16.11.0"
-      },
-      "funding": {
-        "url": "https://github.com/discordjs/discord.js?sponsor"
-      }
-    },
-    "node_modules/@discordjs/ws/node_modules/@discordjs/collection": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz",
-      "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==",
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/discordjs/discord.js?sponsor"
-      }
-    },
-    "node_modules/@eslint-community/eslint-utils": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
-      "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
-      "dev": true,
-      "dependencies": {
-        "eslint-visitor-keys": "^3.3.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "peerDependencies": {
-        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
-      }
-    },
-    "node_modules/@eslint-community/regexpp": {
-      "version": "4.10.0",
-      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
-      "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
-      "dev": true,
-      "engines": {
-        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
-      }
-    },
-    "node_modules/@eslint/eslintrc": {
-      "version": "2.1.4",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
-      "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
-      "dev": true,
-      "dependencies": {
-        "ajv": "^6.12.4",
-        "debug": "^4.3.2",
-        "espree": "^9.6.0",
-        "globals": "^13.19.0",
-        "ignore": "^5.2.0",
-        "import-fresh": "^3.2.1",
-        "js-yaml": "^4.1.0",
-        "minimatch": "^3.1.2",
-        "strip-json-comments": "^3.1.1"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/@eslint/js": {
-      "version": "8.56.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
-      "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
-      "dev": true,
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      }
-    },
-    "node_modules/@humanwhocodes/config-array": {
-      "version": "0.11.13",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
-      "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
-      "dev": true,
-      "dependencies": {
-        "@humanwhocodes/object-schema": "^2.0.1",
-        "debug": "^4.1.1",
-        "minimatch": "^3.0.5"
-      },
-      "engines": {
-        "node": ">=10.10.0"
-      }
-    },
-    "node_modules/@humanwhocodes/module-importer": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
-      "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
-      "dev": true,
-      "engines": {
-        "node": ">=12.22"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/nzakas"
-      }
-    },
-    "node_modules/@humanwhocodes/object-schema": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
-      "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
-      "dev": true
-    },
-    "node_modules/@jridgewell/resolve-uri": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
-      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@jridgewell/sourcemap-codec": {
-      "version": "1.4.14",
-      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
-      "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
-      "dev": true
-    },
-    "node_modules/@jridgewell/trace-mapping": {
-      "version": "0.3.9",
-      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
-      "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
-      "dev": true,
-      "dependencies": {
-        "@jridgewell/resolve-uri": "^3.0.3",
-        "@jridgewell/sourcemap-codec": "^1.4.10"
-      }
-    },
-    "node_modules/@nodelib/fs.scandir": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.stat": "2.0.5",
-        "run-parallel": "^1.1.9"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.stat": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.walk": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.scandir": "2.1.5",
-        "fastq": "^1.6.0"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@sapphire/async-queue": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.2.tgz",
-      "integrity": "sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==",
-      "engines": {
-        "node": ">=v14.0.0",
-        "npm": ">=7.0.0"
-      }
-    },
-    "node_modules/@sapphire/shapeshift": {
-      "version": "3.9.7",
-      "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.7.tgz",
-      "integrity": "sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==",
-      "dependencies": {
-        "fast-deep-equal": "^3.1.3",
-        "lodash": "^4.17.21"
-      },
-      "engines": {
-        "node": ">=v16"
-      }
-    },
-    "node_modules/@sapphire/snowflake": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz",
-      "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==",
-      "engines": {
-        "node": ">=v14.0.0",
-        "npm": ">=7.0.0"
-      }
-    },
-    "node_modules/@tsconfig/node10": {
-      "version": "1.0.9",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
-      "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
-      "dev": true
-    },
-    "node_modules/@tsconfig/node12": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
-      "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
-      "dev": true
-    },
-    "node_modules/@tsconfig/node14": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
-      "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
-      "dev": true
-    },
-    "node_modules/@tsconfig/node16": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
-      "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
-      "dev": true
-    },
-    "node_modules/@types/node": {
-      "version": "20.14.10",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz",
-      "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==",
-      "dependencies": {
-        "undici-types": "~5.26.4"
-      }
-    },
-    "node_modules/@types/ws": {
-      "version": "8.5.10",
-      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
-      "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz",
-      "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==",
-      "dev": true,
-      "dependencies": {
-        "@eslint-community/regexpp": "^4.10.0",
-        "@typescript-eslint/scope-manager": "7.16.0",
-        "@typescript-eslint/type-utils": "7.16.0",
-        "@typescript-eslint/utils": "7.16.0",
-        "@typescript-eslint/visitor-keys": "7.16.0",
-        "graphemer": "^1.4.0",
-        "ignore": "^5.3.1",
-        "natural-compare": "^1.4.0",
-        "ts-api-utils": "^1.3.0"
-      },
-      "engines": {
-        "node": "^18.18.0 || >=20.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependencies": {
-        "@typescript-eslint/parser": "^7.0.0",
-        "eslint": "^8.56.0"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@typescript-eslint/parser": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz",
-      "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/scope-manager": "7.16.0",
-        "@typescript-eslint/types": "7.16.0",
-        "@typescript-eslint/typescript-estree": "7.16.0",
-        "@typescript-eslint/visitor-keys": "7.16.0",
-        "debug": "^4.3.4"
-      },
-      "engines": {
-        "node": "^18.18.0 || >=20.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependencies": {
-        "eslint": "^8.56.0"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@typescript-eslint/scope-manager": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz",
-      "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/types": "7.16.0",
-        "@typescript-eslint/visitor-keys": "7.16.0"
-      },
-      "engines": {
-        "node": "^18.18.0 || >=20.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      }
-    },
-    "node_modules/@typescript-eslint/type-utils": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz",
-      "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/typescript-estree": "7.16.0",
-        "@typescript-eslint/utils": "7.16.0",
-        "debug": "^4.3.4",
-        "ts-api-utils": "^1.3.0"
-      },
-      "engines": {
-        "node": "^18.18.0 || >=20.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependencies": {
-        "eslint": "^8.56.0"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@typescript-eslint/types": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz",
-      "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==",
-      "dev": true,
-      "engines": {
-        "node": "^18.18.0 || >=20.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      }
-    },
-    "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz",
-      "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/types": "7.16.0",
-        "@typescript-eslint/visitor-keys": "7.16.0",
-        "debug": "^4.3.4",
-        "globby": "^11.1.0",
-        "is-glob": "^4.0.3",
-        "minimatch": "^9.0.4",
-        "semver": "^7.6.0",
-        "ts-api-utils": "^1.3.0"
-      },
-      "engines": {
-        "node": "^18.18.0 || >=20.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
-      "dev": true,
-      "dependencies": {
-        "balanced-match": "^1.0.0"
-      }
-    },
-    "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
-      "version": "9.0.5",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
-      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
-      "dev": true,
-      "dependencies": {
-        "brace-expansion": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=16 || 14 >=14.17"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/@typescript-eslint/utils": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz",
-      "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==",
-      "dev": true,
-      "dependencies": {
-        "@eslint-community/eslint-utils": "^4.4.0",
-        "@typescript-eslint/scope-manager": "7.16.0",
-        "@typescript-eslint/types": "7.16.0",
-        "@typescript-eslint/typescript-estree": "7.16.0"
-      },
-      "engines": {
-        "node": "^18.18.0 || >=20.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependencies": {
-        "eslint": "^8.56.0"
-      }
-    },
-    "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz",
-      "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/types": "7.16.0",
-        "eslint-visitor-keys": "^3.4.3"
-      },
-      "engines": {
-        "node": "^18.18.0 || >=20.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      }
-    },
-    "node_modules/@ungap/structured-clone": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
-      "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
-      "dev": true
-    },
-    "node_modules/@vladfrangu/async_event_emitter": {
-      "version": "2.4.3",
-      "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.3.tgz",
-      "integrity": "sha512-wn15EJHUk2RDtCw6wVJndUhFbfJYwyNhSD9s+yiQi5c2MmXDy3KLWvZ5LrcOzt3CHdscoAnaJrxIRKBI1QQgGw==",
-      "engines": {
-        "node": ">=v14.0.0",
-        "npm": ">=7.0.0"
-      }
-    },
-    "node_modules/abbrev": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
-      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
-      "dev": true
-    },
-    "node_modules/acorn": {
-      "version": "8.9.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
-      "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
-      "dev": true,
-      "bin": {
-        "acorn": "bin/acorn"
-      },
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/acorn-jsx": {
-      "version": "5.3.2",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
-      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
-      "dev": true,
-      "peerDependencies": {
-        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
-      }
-    },
-    "node_modules/acorn-walk": {
-      "version": "8.2.0",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
-      "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/ajv": {
-      "version": "6.12.6",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.4.1",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "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==",
-      "dev": true,
-      "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/argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "dev": true
-    },
-    "node_modules/array-union": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
-      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "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/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.3",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
-      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-      "dev": true,
-      "dependencies": {
-        "fill-range": "^7.1.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/callsites": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "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/chalk/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==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/chalk/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==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/chokidar": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
-      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "individual",
-          "url": "https://paulmillr.com/funding/"
-        }
-      ],
-      "dependencies": {
-        "anymatch": "~3.1.2",
-        "braces": "~3.0.2",
-        "glob-parent": "~5.1.2",
-        "is-binary-path": "~2.1.0",
-        "is-glob": "~4.0.1",
-        "normalize-path": "~3.0.0",
-        "readdirp": "~3.6.0"
-      },
-      "engines": {
-        "node": ">= 8.10.0"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.2"
-      }
-    },
-    "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==",
-      "dev": true,
-      "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==",
-      "dev": true
-    },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-      "dev": true
-    },
-    "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/cross-env": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
-      "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
-      "dependencies": {
-        "cross-spawn": "^7.0.1"
-      },
-      "bin": {
-        "cross-env": "src/bin/cross-env.js",
-        "cross-env-shell": "src/bin/cross-env-shell.js"
-      },
-      "engines": {
-        "node": ">=10.14",
-        "npm": ">=6",
-        "yarn": ">=1"
-      }
-    },
-    "node_modules/cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-      "dependencies": {
-        "path-key": "^3.1.0",
-        "shebang-command": "^2.0.0",
-        "which": "^2.0.1"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/debug": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-      "dev": true,
-      "dependencies": {
-        "ms": "2.1.2"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/deep-is": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
-      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-      "dev": true
-    },
-    "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/dir-glob": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
-      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
-      "dev": true,
-      "dependencies": {
-        "path-type": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/discord-api-types": {
-      "version": "0.37.83",
-      "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz",
-      "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA=="
-    },
-    "node_modules/discord.js": {
-      "version": "14.15.3",
-      "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.15.3.tgz",
-      "integrity": "sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ==",
-      "dependencies": {
-        "@discordjs/builders": "^1.8.2",
-        "@discordjs/collection": "1.5.3",
-        "@discordjs/formatters": "^0.4.0",
-        "@discordjs/rest": "^2.3.0",
-        "@discordjs/util": "^1.1.0",
-        "@discordjs/ws": "^1.1.1",
-        "@sapphire/snowflake": "3.5.3",
-        "discord-api-types": "0.37.83",
-        "fast-deep-equal": "3.1.3",
-        "lodash.snakecase": "4.1.1",
-        "tslib": "2.6.2",
-        "undici": "6.13.0"
-      },
-      "engines": {
-        "node": ">=16.11.0"
-      },
-      "funding": {
-        "url": "https://github.com/discordjs/discord.js?sponsor"
-      }
-    },
-    "node_modules/doctrine": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
-      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
-      "dev": true,
-      "dependencies": {
-        "esutils": "^2.0.2"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/dotenv": {
-      "version": "16.4.5",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
-      "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://dotenvx.com"
-      }
-    },
-    "node_modules/escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/eslint": {
-      "version": "8.56.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
-      "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
-      "dev": true,
-      "dependencies": {
-        "@eslint-community/eslint-utils": "^4.2.0",
-        "@eslint-community/regexpp": "^4.6.1",
-        "@eslint/eslintrc": "^2.1.4",
-        "@eslint/js": "8.56.0",
-        "@humanwhocodes/config-array": "^0.11.13",
-        "@humanwhocodes/module-importer": "^1.0.1",
-        "@nodelib/fs.walk": "^1.2.8",
-        "@ungap/structured-clone": "^1.2.0",
-        "ajv": "^6.12.4",
-        "chalk": "^4.0.0",
-        "cross-spawn": "^7.0.2",
-        "debug": "^4.3.2",
-        "doctrine": "^3.0.0",
-        "escape-string-regexp": "^4.0.0",
-        "eslint-scope": "^7.2.2",
-        "eslint-visitor-keys": "^3.4.3",
-        "espree": "^9.6.1",
-        "esquery": "^1.4.2",
-        "esutils": "^2.0.2",
-        "fast-deep-equal": "^3.1.3",
-        "file-entry-cache": "^6.0.1",
-        "find-up": "^5.0.0",
-        "glob-parent": "^6.0.2",
-        "globals": "^13.19.0",
-        "graphemer": "^1.4.0",
-        "ignore": "^5.2.0",
-        "imurmurhash": "^0.1.4",
-        "is-glob": "^4.0.0",
-        "is-path-inside": "^3.0.3",
-        "js-yaml": "^4.1.0",
-        "json-stable-stringify-without-jsonify": "^1.0.1",
-        "levn": "^0.4.1",
-        "lodash.merge": "^4.6.2",
-        "minimatch": "^3.1.2",
-        "natural-compare": "^1.4.0",
-        "optionator": "^0.9.3",
-        "strip-ansi": "^6.0.1",
-        "text-table": "^0.2.0"
-      },
-      "bin": {
-        "eslint": "bin/eslint.js"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/eslint-scope": {
-      "version": "7.2.2",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
-      "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
-      "dev": true,
-      "dependencies": {
-        "esrecurse": "^4.3.0",
-        "estraverse": "^5.2.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/eslint-visitor-keys": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-      "dev": true,
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/eslint/node_modules/glob-parent": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
-      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-      "dev": true,
-      "dependencies": {
-        "is-glob": "^4.0.3"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/espree": {
-      "version": "9.6.1",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
-      "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
-      "dev": true,
-      "dependencies": {
-        "acorn": "^8.9.0",
-        "acorn-jsx": "^5.3.2",
-        "eslint-visitor-keys": "^3.4.1"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/esquery": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
-      "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
-      "dev": true,
-      "dependencies": {
-        "estraverse": "^5.1.0"
-      },
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
-    "node_modules/esrecurse": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
-      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-      "dev": true,
-      "dependencies": {
-        "estraverse": "^5.2.0"
-      },
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/estraverse": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/esutils": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
-    },
-    "node_modules/fast-glob": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
-      "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.stat": "^2.0.2",
-        "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.2",
-        "merge2": "^1.3.0",
-        "micromatch": "^4.0.4"
-      },
-      "engines": {
-        "node": ">=8.6.0"
-      }
-    },
-    "node_modules/fast-json-stable-stringify": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
-      "dev": true
-    },
-    "node_modules/fast-levenshtein": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-      "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-      "dev": true
-    },
-    "node_modules/fastq": {
-      "version": "1.16.0",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
-      "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
-      "dev": true,
-      "dependencies": {
-        "reusify": "^1.0.4"
-      }
-    },
-    "node_modules/file-entry-cache": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
-      "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
-      "dev": true,
-      "dependencies": {
-        "flat-cache": "^3.0.4"
-      },
-      "engines": {
-        "node": "^10.12.0 || >=12.0.0"
-      }
-    },
-    "node_modules/fill-range": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
-      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-      "dev": true,
-      "dependencies": {
-        "to-regex-range": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/find-up": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
-      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
-      "dev": true,
-      "dependencies": {
-        "locate-path": "^6.0.0",
-        "path-exists": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/flat-cache": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
-      "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
-      "dev": true,
-      "dependencies": {
-        "flatted": "^3.2.9",
-        "keyv": "^4.5.3",
-        "rimraf": "^3.0.2"
-      },
-      "engines": {
-        "node": "^10.12.0 || >=12.0.0"
-      }
-    },
-    "node_modules/flatted": {
-      "version": "3.2.9",
-      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
-      "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
-      "dev": true
-    },
-    "node_modules/fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
-      "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/glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "dev": true,
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "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/globals": {
-      "version": "13.24.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
-      "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
-      "dev": true,
-      "dependencies": {
-        "type-fest": "^0.20.2"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/globby": {
-      "version": "11.1.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
-      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
-      "dev": true,
-      "dependencies": {
-        "array-union": "^2.1.0",
-        "dir-glob": "^3.0.1",
-        "fast-glob": "^3.2.9",
-        "ignore": "^5.2.0",
-        "merge2": "^1.4.1",
-        "slash": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/graphemer": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
-      "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-      "dev": true
-    },
-    "node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/ignore": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
-      "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/ignore-by-default": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
-      "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
-      "dev": true
-    },
-    "node_modules/import-fresh": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
-      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-      "dev": true,
-      "dependencies": {
-        "parent-module": "^1.0.0",
-        "resolve-from": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/imurmurhash": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8.19"
-      }
-    },
-    "node_modules/inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "dev": true,
-      "dependencies": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "node_modules/inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "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-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "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-path-inside": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
-      "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
-    },
-    "node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dev": true,
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
-    "node_modules/json-buffer": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
-      "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
-      "dev": true
-    },
-    "node_modules/json-schema-traverse": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-      "dev": true
-    },
-    "node_modules/json-stable-stringify-without-jsonify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-      "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
-      "dev": true
-    },
-    "node_modules/keyv": {
-      "version": "4.5.4",
-      "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
-      "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
-      "dev": true,
-      "dependencies": {
-        "json-buffer": "3.0.1"
-      }
-    },
-    "node_modules/levn": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
-      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
-      "dev": true,
-      "dependencies": {
-        "prelude-ls": "^1.2.1",
-        "type-check": "~0.4.0"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/locate-path": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
-      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
-      "dev": true,
-      "dependencies": {
-        "p-locate": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/lodash": {
-      "version": "4.17.21",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
-    },
-    "node_modules/lodash.merge": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
-      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-      "dev": true
-    },
-    "node_modules/lodash.snakecase": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
-      "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
-    },
-    "node_modules/magic-bytes.js": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz",
-      "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ=="
-    },
-    "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/merge2": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/micromatch": {
-      "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
-      "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
-      "dev": true,
-      "dependencies": {
-        "braces": "^3.0.3",
-        "picomatch": "^2.3.1"
-      },
-      "engines": {
-        "node": ">=8.6"
-      }
-    },
-    "node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "dev": true,
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "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==",
-      "dev": true
-    },
-    "node_modules/natural-compare": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-      "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
-      "dev": true
-    },
-    "node_modules/nodemon": {
-      "version": "3.1.4",
-      "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz",
-      "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==",
-      "dev": true,
-      "dependencies": {
-        "chokidar": "^3.5.2",
-        "debug": "^4",
-        "ignore-by-default": "^1.0.1",
-        "minimatch": "^3.1.2",
-        "pstree.remy": "^1.1.8",
-        "semver": "^7.5.3",
-        "simple-update-notifier": "^2.0.0",
-        "supports-color": "^5.5.0",
-        "touch": "^3.1.0",
-        "undefsafe": "^2.0.5"
-      },
-      "bin": {
-        "nodemon": "bin/nodemon.js"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/nodemon"
-      }
-    },
-    "node_modules/nopt": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
-      "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
-      "dev": true,
-      "dependencies": {
-        "abbrev": "1"
-      },
-      "bin": {
-        "nopt": "bin/nopt.js"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "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/once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "dev": true,
-      "dependencies": {
-        "wrappy": "1"
-      }
-    },
-    "node_modules/optionator": {
-      "version": "0.9.3",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
-      "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
-      "dev": true,
-      "dependencies": {
-        "@aashutoshrathi/word-wrap": "^1.2.3",
-        "deep-is": "^0.1.3",
-        "fast-levenshtein": "^2.0.6",
-        "levn": "^0.4.1",
-        "prelude-ls": "^1.2.1",
-        "type-check": "^0.4.0"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/p-limit": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
-      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
-      "dev": true,
-      "dependencies": {
-        "yocto-queue": "^0.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/p-locate": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
-      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
-      "dev": true,
-      "dependencies": {
-        "p-limit": "^3.0.2"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/parent-module": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
-      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-      "dev": true,
-      "dependencies": {
-        "callsites": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/path-exists": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "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": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/path-key": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/path-type": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true,
-      "engines": {
-        "node": ">=8.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/prelude-ls": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
-      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/prettier": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz",
-      "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==",
-      "dev": true,
-      "bin": {
-        "prettier": "bin/prettier.cjs"
-      },
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/prettier/prettier?sponsor=1"
-      }
-    },
-    "node_modules/pstree.remy": {
-      "version": "1.1.8",
-      "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
-      "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
-      "dev": true
-    },
-    "node_modules/punycode": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
-      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/queue-microtask": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/readdirp": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-      "dev": true,
-      "dependencies": {
-        "picomatch": "^2.2.1"
-      },
-      "engines": {
-        "node": ">=8.10.0"
-      }
-    },
-    "node_modules/resolve-from": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/reusify": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
-      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-      "dev": true,
-      "engines": {
-        "iojs": ">=1.0.0",
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/rimraf": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-      "dev": true,
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/run-parallel": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "dependencies": {
-        "queue-microtask": "^1.2.2"
-      }
-    },
-    "node_modules/semver": {
-      "version": "7.6.2",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
-      "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/shebang-command": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-      "dependencies": {
-        "shebang-regex": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/shebang-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/simple-update-notifier": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
-      "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
-      "dev": true,
-      "dependencies": {
-        "semver": "^7.5.3"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/slash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
-      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-ansi": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
-      "dependencies": {
-        "ansi-regex": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-json-comments": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/text-table": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-      "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
-      "dev": true
-    },
-    "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/touch": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
-      "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
-      "dev": true,
-      "dependencies": {
-        "nopt": "~1.0.10"
-      },
-      "bin": {
-        "nodetouch": "bin/nodetouch.js"
-      }
-    },
-    "node_modules/ts-api-utils": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
-      "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=16"
-      },
-      "peerDependencies": {
-        "typescript": ">=4.2.0"
-      }
-    },
-    "node_modules/ts-mixer": {
-      "version": "6.0.4",
-      "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
-      "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="
-    },
-    "node_modules/ts-node": {
-      "version": "10.9.2",
-      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
-      "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
-      "dev": true,
-      "dependencies": {
-        "@cspotcode/source-map-support": "^0.8.0",
-        "@tsconfig/node10": "^1.0.7",
-        "@tsconfig/node12": "^1.0.7",
-        "@tsconfig/node14": "^1.0.0",
-        "@tsconfig/node16": "^1.0.2",
-        "acorn": "^8.4.1",
-        "acorn-walk": "^8.1.1",
-        "arg": "^4.1.0",
-        "create-require": "^1.1.0",
-        "diff": "^4.0.1",
-        "make-error": "^1.1.1",
-        "v8-compile-cache-lib": "^3.0.1",
-        "yn": "3.1.1"
-      },
-      "bin": {
-        "ts-node": "dist/bin.js",
-        "ts-node-cwd": "dist/bin-cwd.js",
-        "ts-node-esm": "dist/bin-esm.js",
-        "ts-node-script": "dist/bin-script.js",
-        "ts-node-transpile-only": "dist/bin-transpile.js",
-        "ts-script": "dist/bin-script-deprecated.js"
-      },
-      "peerDependencies": {
-        "@swc/core": ">=1.2.50",
-        "@swc/wasm": ">=1.2.50",
-        "@types/node": "*",
-        "typescript": ">=2.7"
-      },
-      "peerDependenciesMeta": {
-        "@swc/core": {
-          "optional": true
-        },
-        "@swc/wasm": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/tslib": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
-      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
-    },
-    "node_modules/type-check": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
-      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
-      "dev": true,
-      "dependencies": {
-        "prelude-ls": "^1.2.1"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/type-fest": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
-      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/typescript": {
-      "version": "5.5.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
-      "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
-      "dev": true,
-      "bin": {
-        "tsc": "bin/tsc",
-        "tsserver": "bin/tsserver"
-      },
-      "engines": {
-        "node": ">=14.17"
-      }
-    },
-    "node_modules/undefsafe": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
-      "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
-      "dev": true
-    },
-    "node_modules/undici": {
-      "version": "6.13.0",
-      "resolved": "https://registry.npmjs.org/undici/-/undici-6.13.0.tgz",
-      "integrity": "sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==",
-      "engines": {
-        "node": ">=18.0"
-      }
-    },
-    "node_modules/undici-types": {
-      "version": "5.26.5",
-      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
-      "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
-    },
-    "node_modules/uri-js": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-      "dev": true,
-      "dependencies": {
-        "punycode": "^2.1.0"
-      }
-    },
-    "node_modules/v8-compile-cache-lib": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
-      "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
-      "dev": true
-    },
-    "node_modules/which": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-      "dependencies": {
-        "isexe": "^2.0.0"
-      },
-      "bin": {
-        "node-which": "bin/node-which"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
-      "dev": true
-    },
-    "node_modules/ws": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
-      "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
-      "engines": {
-        "node": ">=10.0.0"
-      },
-      "peerDependencies": {
-        "bufferutil": "^4.0.1",
-        "utf-8-validate": ">=5.0.2"
-      },
-      "peerDependenciesMeta": {
-        "bufferutil": {
-          "optional": true
-        },
-        "utf-8-validate": {
-          "optional": true
-        }
-      }
-    },
-    "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"
-      }
-    },
-    "node_modules/yocto-queue": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
-      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    }
-  },
-  "dependencies": {
-    "@aashutoshrathi/word-wrap": {
-      "version": "1.2.6",
-      "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
-      "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
-      "dev": true
-    },
-    "@cspotcode/source-map-support": {
-      "version": "0.8.1",
-      "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
-      "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
-      "dev": true,
-      "requires": {
-        "@jridgewell/trace-mapping": "0.3.9"
-      }
-    },
-    "@discordjs/builders": {
-      "version": "1.8.2",
-      "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.8.2.tgz",
-      "integrity": "sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==",
-      "requires": {
-        "@discordjs/formatters": "^0.4.0",
-        "@discordjs/util": "^1.1.0",
-        "@sapphire/shapeshift": "^3.9.7",
-        "discord-api-types": "0.37.83",
-        "fast-deep-equal": "^3.1.3",
-        "ts-mixer": "^6.0.4",
-        "tslib": "^2.6.2"
-      }
-    },
-    "@discordjs/collection": {
-      "version": "1.5.3",
-      "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz",
-      "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ=="
-    },
-    "@discordjs/formatters": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.4.0.tgz",
-      "integrity": "sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==",
-      "requires": {
-        "discord-api-types": "0.37.83"
-      }
-    },
-    "@discordjs/rest": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.3.0.tgz",
-      "integrity": "sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==",
-      "requires": {
-        "@discordjs/collection": "^2.1.0",
-        "@discordjs/util": "^1.1.0",
-        "@sapphire/async-queue": "^1.5.2",
-        "@sapphire/snowflake": "^3.5.3",
-        "@vladfrangu/async_event_emitter": "^2.2.4",
-        "discord-api-types": "0.37.83",
-        "magic-bytes.js": "^1.10.0",
-        "tslib": "^2.6.2",
-        "undici": "6.13.0"
-      },
-      "dependencies": {
-        "@discordjs/collection": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz",
-          "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw=="
-        }
-      }
-    },
-    "@discordjs/util": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.0.tgz",
-      "integrity": "sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg=="
-    },
-    "@discordjs/ws": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.1.tgz",
-      "integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==",
-      "requires": {
-        "@discordjs/collection": "^2.1.0",
-        "@discordjs/rest": "^2.3.0",
-        "@discordjs/util": "^1.1.0",
-        "@sapphire/async-queue": "^1.5.2",
-        "@types/ws": "^8.5.10",
-        "@vladfrangu/async_event_emitter": "^2.2.4",
-        "discord-api-types": "0.37.83",
-        "tslib": "^2.6.2",
-        "ws": "^8.16.0"
-      },
-      "dependencies": {
-        "@discordjs/collection": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz",
-          "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw=="
-        }
-      }
-    },
-    "@eslint-community/eslint-utils": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
-      "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
-      "dev": true,
-      "requires": {
-        "eslint-visitor-keys": "^3.3.0"
-      }
-    },
-    "@eslint-community/regexpp": {
-      "version": "4.10.0",
-      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
-      "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
-      "dev": true
-    },
-    "@eslint/eslintrc": {
-      "version": "2.1.4",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
-      "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
-      "dev": true,
-      "requires": {
-        "ajv": "^6.12.4",
-        "debug": "^4.3.2",
-        "espree": "^9.6.0",
-        "globals": "^13.19.0",
-        "ignore": "^5.2.0",
-        "import-fresh": "^3.2.1",
-        "js-yaml": "^4.1.0",
-        "minimatch": "^3.1.2",
-        "strip-json-comments": "^3.1.1"
-      }
-    },
-    "@eslint/js": {
-      "version": "8.56.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
-      "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
-      "dev": true
-    },
-    "@humanwhocodes/config-array": {
-      "version": "0.11.13",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
-      "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
-      "dev": true,
-      "requires": {
-        "@humanwhocodes/object-schema": "^2.0.1",
-        "debug": "^4.1.1",
-        "minimatch": "^3.0.5"
-      }
-    },
-    "@humanwhocodes/module-importer": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
-      "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
-      "dev": true
-    },
-    "@humanwhocodes/object-schema": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
-      "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
-      "dev": true
-    },
-    "@jridgewell/resolve-uri": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
-      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
-      "dev": true
-    },
-    "@jridgewell/sourcemap-codec": {
-      "version": "1.4.14",
-      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
-      "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
-      "dev": true
-    },
-    "@jridgewell/trace-mapping": {
-      "version": "0.3.9",
-      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
-      "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
-      "dev": true,
-      "requires": {
-        "@jridgewell/resolve-uri": "^3.0.3",
-        "@jridgewell/sourcemap-codec": "^1.4.10"
-      }
-    },
-    "@nodelib/fs.scandir": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.stat": "2.0.5",
-        "run-parallel": "^1.1.9"
-      }
-    },
-    "@nodelib/fs.stat": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-      "dev": true
-    },
-    "@nodelib/fs.walk": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.scandir": "2.1.5",
-        "fastq": "^1.6.0"
-      }
-    },
-    "@sapphire/async-queue": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.2.tgz",
-      "integrity": "sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg=="
-    },
-    "@sapphire/shapeshift": {
-      "version": "3.9.7",
-      "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.7.tgz",
-      "integrity": "sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==",
-      "requires": {
-        "fast-deep-equal": "^3.1.3",
-        "lodash": "^4.17.21"
-      }
-    },
-    "@sapphire/snowflake": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz",
-      "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ=="
-    },
-    "@tsconfig/node10": {
-      "version": "1.0.9",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
-      "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
-      "dev": true
-    },
-    "@tsconfig/node12": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
-      "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
-      "dev": true
-    },
-    "@tsconfig/node14": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
-      "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
-      "dev": true
-    },
-    "@tsconfig/node16": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
-      "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
-      "dev": true
-    },
-    "@types/node": {
-      "version": "20.14.10",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz",
-      "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==",
-      "requires": {
-        "undici-types": "~5.26.4"
-      }
-    },
-    "@types/ws": {
-      "version": "8.5.10",
-      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
-      "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
-      "requires": {
-        "@types/node": "*"
-      }
-    },
-    "@typescript-eslint/eslint-plugin": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz",
-      "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==",
-      "dev": true,
-      "requires": {
-        "@eslint-community/regexpp": "^4.10.0",
-        "@typescript-eslint/scope-manager": "7.16.0",
-        "@typescript-eslint/type-utils": "7.16.0",
-        "@typescript-eslint/utils": "7.16.0",
-        "@typescript-eslint/visitor-keys": "7.16.0",
-        "graphemer": "^1.4.0",
-        "ignore": "^5.3.1",
-        "natural-compare": "^1.4.0",
-        "ts-api-utils": "^1.3.0"
-      }
-    },
-    "@typescript-eslint/parser": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz",
-      "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/scope-manager": "7.16.0",
-        "@typescript-eslint/types": "7.16.0",
-        "@typescript-eslint/typescript-estree": "7.16.0",
-        "@typescript-eslint/visitor-keys": "7.16.0",
-        "debug": "^4.3.4"
-      }
-    },
-    "@typescript-eslint/scope-manager": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz",
-      "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/types": "7.16.0",
-        "@typescript-eslint/visitor-keys": "7.16.0"
-      }
-    },
-    "@typescript-eslint/type-utils": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz",
-      "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/typescript-estree": "7.16.0",
-        "@typescript-eslint/utils": "7.16.0",
-        "debug": "^4.3.4",
-        "ts-api-utils": "^1.3.0"
-      }
-    },
-    "@typescript-eslint/types": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz",
-      "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==",
-      "dev": true
-    },
-    "@typescript-eslint/typescript-estree": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz",
-      "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/types": "7.16.0",
-        "@typescript-eslint/visitor-keys": "7.16.0",
-        "debug": "^4.3.4",
-        "globby": "^11.1.0",
-        "is-glob": "^4.0.3",
-        "minimatch": "^9.0.4",
-        "semver": "^7.6.0",
-        "ts-api-utils": "^1.3.0"
-      },
-      "dependencies": {
-        "brace-expansion": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-          "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
-          "dev": true,
-          "requires": {
-            "balanced-match": "^1.0.0"
-          }
-        },
-        "minimatch": {
-          "version": "9.0.5",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
-          "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
-          "dev": true,
-          "requires": {
-            "brace-expansion": "^2.0.1"
-          }
-        }
-      }
-    },
-    "@typescript-eslint/utils": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz",
-      "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==",
-      "dev": true,
-      "requires": {
-        "@eslint-community/eslint-utils": "^4.4.0",
-        "@typescript-eslint/scope-manager": "7.16.0",
-        "@typescript-eslint/types": "7.16.0",
-        "@typescript-eslint/typescript-estree": "7.16.0"
-      }
-    },
-    "@typescript-eslint/visitor-keys": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz",
-      "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/types": "7.16.0",
-        "eslint-visitor-keys": "^3.4.3"
-      }
-    },
-    "@ungap/structured-clone": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
-      "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
-      "dev": true
-    },
-    "@vladfrangu/async_event_emitter": {
-      "version": "2.4.3",
-      "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.3.tgz",
-      "integrity": "sha512-wn15EJHUk2RDtCw6wVJndUhFbfJYwyNhSD9s+yiQi5c2MmXDy3KLWvZ5LrcOzt3CHdscoAnaJrxIRKBI1QQgGw=="
-    },
-    "abbrev": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
-      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
-      "dev": true
-    },
-    "acorn": {
-      "version": "8.9.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
-      "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
-      "dev": true
-    },
-    "acorn-jsx": {
-      "version": "5.3.2",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
-      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
-      "dev": true,
-      "requires": {}
-    },
-    "acorn-walk": {
-      "version": "8.2.0",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
-      "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
-      "dev": true
-    },
-    "ajv": {
-      "version": "6.12.6",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-      "dev": true,
-      "requires": {
-        "fast-deep-equal": "^3.1.1",
-        "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.4.1",
-        "uri-js": "^4.2.2"
-      }
-    },
-    "ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true
-    },
-    "ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "requires": {
-        "color-convert": "^2.0.1"
-      }
-    },
-    "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
-    },
-    "argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "dev": true
-    },
-    "array-union": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
-      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
-      "dev": true
-    },
-    "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
-    },
-    "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.3",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
-      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-      "dev": true,
-      "requires": {
-        "fill-range": "^7.1.1"
-      }
-    },
-    "callsites": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-      "dev": true
-    },
-    "chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "requires": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "dependencies": {
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        }
-      }
-    },
-    "chokidar": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
-      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-      "dev": true,
-      "requires": {
-        "anymatch": "~3.1.2",
-        "braces": "~3.0.2",
-        "fsevents": "~2.3.2",
-        "glob-parent": "~5.1.2",
-        "is-binary-path": "~2.1.0",
-        "is-glob": "~4.0.1",
-        "normalize-path": "~3.0.0",
-        "readdirp": "~3.6.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==",
-      "dev": true,
-      "requires": {
-        "color-name": "~1.1.4"
-      }
-    },
-    "color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-      "dev": true
-    },
-    "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
-    },
-    "cross-env": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
-      "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
-      "requires": {
-        "cross-spawn": "^7.0.1"
-      }
-    },
-    "cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-      "requires": {
-        "path-key": "^3.1.0",
-        "shebang-command": "^2.0.0",
-        "which": "^2.0.1"
-      }
-    },
-    "debug": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-      "dev": true,
-      "requires": {
-        "ms": "2.1.2"
-      }
-    },
-    "deep-is": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
-      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-      "dev": true
-    },
-    "diff": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-      "dev": true
-    },
-    "dir-glob": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
-      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
-      "dev": true,
-      "requires": {
-        "path-type": "^4.0.0"
-      }
-    },
-    "discord-api-types": {
-      "version": "0.37.83",
-      "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz",
-      "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA=="
-    },
-    "discord.js": {
-      "version": "14.15.3",
-      "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.15.3.tgz",
-      "integrity": "sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ==",
-      "requires": {
-        "@discordjs/builders": "^1.8.2",
-        "@discordjs/collection": "1.5.3",
-        "@discordjs/formatters": "^0.4.0",
-        "@discordjs/rest": "^2.3.0",
-        "@discordjs/util": "^1.1.0",
-        "@discordjs/ws": "^1.1.1",
-        "@sapphire/snowflake": "3.5.3",
-        "discord-api-types": "0.37.83",
-        "fast-deep-equal": "3.1.3",
-        "lodash.snakecase": "4.1.1",
-        "tslib": "2.6.2",
-        "undici": "6.13.0"
-      }
-    },
-    "doctrine": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
-      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
-      "dev": true,
-      "requires": {
-        "esutils": "^2.0.2"
-      }
-    },
-    "dotenv": {
-      "version": "16.4.5",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
-      "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg=="
-    },
-    "escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "dev": true
-    },
-    "eslint": {
-      "version": "8.56.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
-      "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
-      "dev": true,
-      "requires": {
-        "@eslint-community/eslint-utils": "^4.2.0",
-        "@eslint-community/regexpp": "^4.6.1",
-        "@eslint/eslintrc": "^2.1.4",
-        "@eslint/js": "8.56.0",
-        "@humanwhocodes/config-array": "^0.11.13",
-        "@humanwhocodes/module-importer": "^1.0.1",
-        "@nodelib/fs.walk": "^1.2.8",
-        "@ungap/structured-clone": "^1.2.0",
-        "ajv": "^6.12.4",
-        "chalk": "^4.0.0",
-        "cross-spawn": "^7.0.2",
-        "debug": "^4.3.2",
-        "doctrine": "^3.0.0",
-        "escape-string-regexp": "^4.0.0",
-        "eslint-scope": "^7.2.2",
-        "eslint-visitor-keys": "^3.4.3",
-        "espree": "^9.6.1",
-        "esquery": "^1.4.2",
-        "esutils": "^2.0.2",
-        "fast-deep-equal": "^3.1.3",
-        "file-entry-cache": "^6.0.1",
-        "find-up": "^5.0.0",
-        "glob-parent": "^6.0.2",
-        "globals": "^13.19.0",
-        "graphemer": "^1.4.0",
-        "ignore": "^5.2.0",
-        "imurmurhash": "^0.1.4",
-        "is-glob": "^4.0.0",
-        "is-path-inside": "^3.0.3",
-        "js-yaml": "^4.1.0",
-        "json-stable-stringify-without-jsonify": "^1.0.1",
-        "levn": "^0.4.1",
-        "lodash.merge": "^4.6.2",
-        "minimatch": "^3.1.2",
-        "natural-compare": "^1.4.0",
-        "optionator": "^0.9.3",
-        "strip-ansi": "^6.0.1",
-        "text-table": "^0.2.0"
-      },
-      "dependencies": {
-        "glob-parent": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
-          "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-          "dev": true,
-          "requires": {
-            "is-glob": "^4.0.3"
-          }
-        }
-      }
-    },
-    "eslint-scope": {
-      "version": "7.2.2",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
-      "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
-      "dev": true,
-      "requires": {
-        "esrecurse": "^4.3.0",
-        "estraverse": "^5.2.0"
-      }
-    },
-    "eslint-visitor-keys": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-      "dev": true
-    },
-    "espree": {
-      "version": "9.6.1",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
-      "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
-      "dev": true,
-      "requires": {
-        "acorn": "^8.9.0",
-        "acorn-jsx": "^5.3.2",
-        "eslint-visitor-keys": "^3.4.1"
-      }
-    },
-    "esquery": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
-      "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
-      "dev": true,
-      "requires": {
-        "estraverse": "^5.1.0"
-      }
-    },
-    "esrecurse": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
-      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-      "dev": true,
-      "requires": {
-        "estraverse": "^5.2.0"
-      }
-    },
-    "estraverse": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-      "dev": true
-    },
-    "esutils": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-      "dev": true
-    },
-    "fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
-    },
-    "fast-glob": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
-      "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.stat": "^2.0.2",
-        "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.2",
-        "merge2": "^1.3.0",
-        "micromatch": "^4.0.4"
-      }
-    },
-    "fast-json-stable-stringify": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
-      "dev": true
-    },
-    "fast-levenshtein": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-      "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-      "dev": true
-    },
-    "fastq": {
-      "version": "1.16.0",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
-      "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
-      "dev": true,
-      "requires": {
-        "reusify": "^1.0.4"
-      }
-    },
-    "file-entry-cache": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
-      "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
-      "dev": true,
-      "requires": {
-        "flat-cache": "^3.0.4"
-      }
-    },
-    "fill-range": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
-      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-      "dev": true,
-      "requires": {
-        "to-regex-range": "^5.0.1"
-      }
-    },
-    "find-up": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
-      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
-      "dev": true,
-      "requires": {
-        "locate-path": "^6.0.0",
-        "path-exists": "^4.0.0"
-      }
-    },
-    "flat-cache": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
-      "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
-      "dev": true,
-      "requires": {
-        "flatted": "^3.2.9",
-        "keyv": "^4.5.3",
-        "rimraf": "^3.0.2"
-      }
-    },
-    "flatted": {
-      "version": "3.2.9",
-      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
-      "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
-      "dev": true
-    },
-    "fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
-      "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
-    },
-    "glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "dev": true,
-      "requires": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "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"
-      }
-    },
-    "globals": {
-      "version": "13.24.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
-      "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
-      "dev": true,
-      "requires": {
-        "type-fest": "^0.20.2"
-      }
-    },
-    "globby": {
-      "version": "11.1.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
-      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
-      "dev": true,
-      "requires": {
-        "array-union": "^2.1.0",
-        "dir-glob": "^3.0.1",
-        "fast-glob": "^3.2.9",
-        "ignore": "^5.2.0",
-        "merge2": "^1.4.1",
-        "slash": "^3.0.0"
-      }
-    },
-    "graphemer": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
-      "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-      "dev": true
-    },
-    "has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "dev": true
-    },
-    "ignore": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
-      "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
-      "dev": true
-    },
-    "ignore-by-default": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
-      "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
-      "dev": true
-    },
-    "import-fresh": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
-      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-      "dev": true,
-      "requires": {
-        "parent-module": "^1.0.0",
-        "resolve-from": "^4.0.0"
-      }
-    },
-    "imurmurhash": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
-      "dev": true
-    },
-    "inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "dev": true,
-      "requires": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "dev": true
-    },
-    "is-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-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true
-    },
-    "is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "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-path-inside": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
-      "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
-      "dev": true
-    },
-    "isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
-    },
-    "js-yaml": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dev": true,
-      "requires": {
-        "argparse": "^2.0.1"
-      }
-    },
-    "json-buffer": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
-      "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
-      "dev": true
-    },
-    "json-schema-traverse": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-      "dev": true
-    },
-    "json-stable-stringify-without-jsonify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-      "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
-      "dev": true
-    },
-    "keyv": {
-      "version": "4.5.4",
-      "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
-      "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
-      "dev": true,
-      "requires": {
-        "json-buffer": "3.0.1"
-      }
-    },
-    "levn": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
-      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "^1.2.1",
-        "type-check": "~0.4.0"
-      }
-    },
-    "locate-path": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
-      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
-      "dev": true,
-      "requires": {
-        "p-locate": "^5.0.0"
-      }
-    },
-    "lodash": {
-      "version": "4.17.21",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
-    },
-    "lodash.merge": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
-      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-      "dev": true
-    },
-    "lodash.snakecase": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
-      "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
-    },
-    "magic-bytes.js": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz",
-      "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ=="
-    },
-    "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
-    },
-    "merge2": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-      "dev": true
-    },
-    "micromatch": {
-      "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
-      "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
-      "dev": true,
-      "requires": {
-        "braces": "^3.0.3",
-        "picomatch": "^2.3.1"
-      }
-    },
-    "minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "dev": true,
-      "requires": {
-        "brace-expansion": "^1.1.7"
-      }
-    },
-    "ms": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-      "dev": true
-    },
-    "natural-compare": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-      "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
-      "dev": true
-    },
-    "nodemon": {
-      "version": "3.1.4",
-      "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz",
-      "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==",
-      "dev": true,
-      "requires": {
-        "chokidar": "^3.5.2",
-        "debug": "^4",
-        "ignore-by-default": "^1.0.1",
-        "minimatch": "^3.1.2",
-        "pstree.remy": "^1.1.8",
-        "semver": "^7.5.3",
-        "simple-update-notifier": "^2.0.0",
-        "supports-color": "^5.5.0",
-        "touch": "^3.1.0",
-        "undefsafe": "^2.0.5"
-      }
-    },
-    "nopt": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
-      "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
-      "dev": true,
-      "requires": {
-        "abbrev": "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
-    },
-    "once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "dev": true,
-      "requires": {
-        "wrappy": "1"
-      }
-    },
-    "optionator": {
-      "version": "0.9.3",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
-      "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
-      "dev": true,
-      "requires": {
-        "@aashutoshrathi/word-wrap": "^1.2.3",
-        "deep-is": "^0.1.3",
-        "fast-levenshtein": "^2.0.6",
-        "levn": "^0.4.1",
-        "prelude-ls": "^1.2.1",
-        "type-check": "^0.4.0"
-      }
-    },
-    "p-limit": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
-      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
-      "dev": true,
-      "requires": {
-        "yocto-queue": "^0.1.0"
-      }
-    },
-    "p-locate": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
-      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
-      "dev": true,
-      "requires": {
-        "p-limit": "^3.0.2"
-      }
-    },
-    "parent-module": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
-      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-      "dev": true,
-      "requires": {
-        "callsites": "^3.0.0"
-      }
-    },
-    "path-exists": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-      "dev": true
-    },
-    "path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-      "dev": true
-    },
-    "path-key": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
-    },
-    "path-type": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-      "dev": true
-    },
-    "picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true
-    },
-    "prelude-ls": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
-      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-      "dev": true
-    },
-    "prettier": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz",
-      "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==",
-      "dev": true
-    },
-    "pstree.remy": {
-      "version": "1.1.8",
-      "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
-      "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
-      "dev": true
-    },
-    "punycode": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
-      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
-      "dev": true
-    },
-    "queue-microtask": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-      "dev": true
-    },
-    "readdirp": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-      "dev": true,
-      "requires": {
-        "picomatch": "^2.2.1"
-      }
-    },
-    "resolve-from": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-      "dev": true
-    },
-    "reusify": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
-      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-      "dev": true
-    },
-    "rimraf": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-      "dev": true,
-      "requires": {
-        "glob": "^7.1.3"
-      }
-    },
-    "run-parallel": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-      "dev": true,
-      "requires": {
-        "queue-microtask": "^1.2.2"
-      }
-    },
-    "semver": {
-      "version": "7.6.2",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
-      "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
-      "dev": true
-    },
-    "shebang-command": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-      "requires": {
-        "shebang-regex": "^3.0.0"
-      }
-    },
-    "shebang-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
-    },
-    "simple-update-notifier": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
-      "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
-      "dev": true,
-      "requires": {
-        "semver": "^7.5.3"
-      }
-    },
-    "slash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
-      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
-      "dev": true
-    },
-    "strip-ansi": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
-      "requires": {
-        "ansi-regex": "^5.0.1"
-      }
-    },
-    "strip-json-comments": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-      "dev": true
-    },
-    "supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
-      "requires": {
-        "has-flag": "^3.0.0"
-      }
-    },
-    "text-table": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-      "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
-      "dev": true
-    },
-    "to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
-      "requires": {
-        "is-number": "^7.0.0"
-      }
-    },
-    "touch": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
-      "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
-      "dev": true,
-      "requires": {
-        "nopt": "~1.0.10"
-      }
-    },
-    "ts-api-utils": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
-      "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
-      "dev": true,
-      "requires": {}
-    },
-    "ts-mixer": {
-      "version": "6.0.4",
-      "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
-      "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="
-    },
-    "ts-node": {
-      "version": "10.9.2",
-      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
-      "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
-      "dev": true,
-      "requires": {
-        "@cspotcode/source-map-support": "^0.8.0",
-        "@tsconfig/node10": "^1.0.7",
-        "@tsconfig/node12": "^1.0.7",
-        "@tsconfig/node14": "^1.0.0",
-        "@tsconfig/node16": "^1.0.2",
-        "acorn": "^8.4.1",
-        "acorn-walk": "^8.1.1",
-        "arg": "^4.1.0",
-        "create-require": "^1.1.0",
-        "diff": "^4.0.1",
-        "make-error": "^1.1.1",
-        "v8-compile-cache-lib": "^3.0.1",
-        "yn": "3.1.1"
-      }
-    },
-    "tslib": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
-      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
-    },
-    "type-check": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
-      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "^1.2.1"
-      }
-    },
-    "type-fest": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
-      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
-      "dev": true
-    },
-    "typescript": {
-      "version": "5.5.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
-      "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
-      "dev": true
-    },
-    "undefsafe": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
-      "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
-      "dev": true
-    },
-    "undici": {
-      "version": "6.13.0",
-      "resolved": "https://registry.npmjs.org/undici/-/undici-6.13.0.tgz",
-      "integrity": "sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw=="
-    },
-    "undici-types": {
-      "version": "5.26.5",
-      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
-      "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
-    },
-    "uri-js": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-      "dev": true,
-      "requires": {
-        "punycode": "^2.1.0"
-      }
-    },
-    "v8-compile-cache-lib": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
-      "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
-      "dev": true
-    },
-    "which": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-      "requires": {
-        "isexe": "^2.0.0"
-      }
-    },
-    "wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
-      "dev": true
-    },
-    "ws": {
-      "version": "8.18.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
-      "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
-      "requires": {}
-    },
-    "yn": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
-      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-      "dev": true
-    },
-    "yocto-queue": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
-      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
-      "dev": true
-    }
-  }
-}
diff --git a/package.json b/package.json
deleted file mode 100644
index 9211a05..0000000
--- a/package.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-  "name": "discord-bot-template",
-  "version": "1.0.0",
-  "description": "Discord bot created from a TypeScript template",
-  "main": "dist/index.js",
-  "scripts": {
-    "build": "tsc",
-    "start": "node .",
-    "dev": "nodemon --config nodemon.json src/index.ts",
-    "deploy": "cross-env IS_SCRIPT=true ts-node src/scripts/deploy",
-    "deploy:prod": "cross-env NODE_ENV=production npm run deploy",
-    "clear": "cross-env IS_SCRIPT=true ts-node src/scripts/clear",
-    "format": "prettier --write ./src",
-    "format:check": "prettier --check ./src"
-  },
-  "keywords": [],
-  "author": "",
-  "license": "MIT",
-  "devDependencies": {
-    "@types/node": "^20.14.10",
-    "@typescript-eslint/eslint-plugin": "^7.16.0",
-    "@typescript-eslint/parser": "^7.16.0",
-    "eslint": "^8.56.0",
-    "nodemon": "^3.1.4",
-    "prettier": "^3.3.2",
-    "ts-node": "^10.9.2",
-    "typescript": "^5.5.3"
-  },
-  "dependencies": {
-    "cross-env": "^7.0.3",
-    "discord.js": "^14.15.3",
-    "dotenv": "^16.4.5"
-  }
-}
diff --git a/src/client/index.ts b/src/client/index.ts
index b57e4a2..61c29d0 100644
--- a/src/client/index.ts
+++ b/src/client/index.ts
@@ -1,13 +1,14 @@
-import { Client, GatewayIntentBits } from 'discord.js';
-import { log } from '../utils';
-import { ENV } from '../env';
+import process from "node:process";
+import { Client, GatewayIntentBits } from "discord.js";
+import { log } from "utils";
+import ENV from "env";
 
 const client = new Client({
   intents: [GatewayIntentBits.Guilds],
 });
 
 client.login(ENV.BOT_TOKEN).catch((err) => {
-  log.error('login', err);
+  log.error("login", err);
   process.exit(1);
 });
 
diff --git a/src/commands/debug/index.ts b/src/commands/debug/index.ts
index bcefe36..05c347c 100644
--- a/src/commands/debug/index.ts
+++ b/src/commands/debug/index.ts
@@ -1,7 +1,7 @@
-import { category } from '../../utils';
-import ping from './ping';
+import { category } from "utils";
+import ping from "./ping.ts";
 
 export default category(
-  { name: 'Debug', description: 'Commands used for debugging.', emoji: '🐛' },
+  { name: "Debug", description: "Commands used for debugging.", emoji: "🐛" },
   [ping]
 );
diff --git a/src/commands/debug/ping.ts b/src/commands/debug/ping.ts
index 623e0a7..2abb65c 100644
--- a/src/commands/debug/ping.ts
+++ b/src/commands/debug/ping.ts
@@ -1,13 +1,13 @@
-import { SlashCommandBuilder } from 'discord.js';
-import { command, reply } from '../../utils';
+import { SlashCommandBuilder } from "discord.js";
+import { command, reply } from "utils";
 
 const meta = new SlashCommandBuilder()
-  .setName('ping')
-  .setDescription('Ping the bot for a response.')
+  .setName("ping")
+  .setDescription("Ping the bot for a response.")
   .addStringOption((option) =>
     option
-      .setName('message')
-      .setDescription('Provide the bot a message to respond with.')
+      .setName("message")
+      .setDescription("Provide the bot a message to respond with.")
       .setMinLength(1)
       .setMaxLength(2000)
       .setRequired(false)
@@ -17,11 +17,11 @@ export default command({
   meta,
   private: true,
   exec: async ({ client, interaction }) => {
-    const message = interaction.options.getString('message');
+    const message = interaction.options.getString("message");
 
     await reply(interaction, {
       ephemeral: true,
-      content: `${message ?? 'Pong!'} (${client.ws.ping}ms)`,
+      content: `${message ?? "Pong!"} (${client.ws.ping}ms)`,
     });
   },
 });
diff --git a/src/commands/general/help.ts b/src/commands/general/help.ts
index caea298..f292c3b 100644
--- a/src/commands/general/help.ts
+++ b/src/commands/general/help.ts
@@ -1,25 +1,25 @@
-import { EmbedBuilder, SlashCommandBuilder } from 'discord.js';
-import { command, helpSelectComponent, reply } from '../../utils';
-import { COLORS } from '../../constants';
+import { EmbedBuilder, SlashCommandBuilder } from "discord.js";
+import { command, helpSelectComponent, reply } from "utils";
+import { COLORS } from "utils";
 
 const meta = new SlashCommandBuilder()
-  .setName('help')
-  .setDescription('Get a list of all commands for the bot.');
+  .setName("help")
+  .setDescription("Get a list of all commands for the bot.");
 
 export default command({
   meta,
   exec: async ({ interaction }) => {
     const embed = new EmbedBuilder()
-      .setTitle('Help Menu')
+      .setTitle("Help Menu")
       .setDescription(
-        'Browse through all available commands by selecting a category below.'
+        "Browse through all available commands by selecting a category below."
       )
       .setColor(COLORS.embed);
 
     const helpSelectMenu = helpSelectComponent(interaction);
     if (!helpSelectMenu) {
       embed.setDescription(
-        'There are no commands available for you to use in this server.'
+        "There are no commands available for you to use in this server."
       );
       return await reply(interaction, {
         embeds: [embed],
diff --git a/src/commands/general/index.ts b/src/commands/general/index.ts
index ae55fa2..53a6e84 100644
--- a/src/commands/general/index.ts
+++ b/src/commands/general/index.ts
@@ -1,12 +1,12 @@
-import { category } from '../../utils';
-import help from './help';
-import info from './info';
+import { category } from "utils";
+import help from "./help.ts";
+import info from "./info.ts";
 
 export default category(
   {
-    name: 'General',
-    description: 'General bot commands.',
-    emoji: '📖',
+    name: "General",
+    description: "General bot commands.",
+    emoji: "📖",
   },
   [help, info]
 );
diff --git a/src/commands/general/info.ts b/src/commands/general/info.ts
index 6637116..7153a82 100644
--- a/src/commands/general/info.ts
+++ b/src/commands/general/info.ts
@@ -2,32 +2,31 @@ import {
   EmbedBuilder,
   SlashCommandBuilder,
   SlashCommandSubcommandBuilder,
-} from 'discord.js';
-import { command, formatDate, reply } from '../../utils';
-import { COLORS } from '../../constants';
-import { CommandContext } from '../../types';
+} from "discord.js";
+import { command, formatDate, reply, COLORS } from "utils";
+import { CommandContext } from "types";
 
 const server = new SlashCommandSubcommandBuilder()
-  .setName('server')
-  .setDescription('Get some info about this server.');
+  .setName("server")
+  .setDescription("Get some info about this server.");
 
 const bot = new SlashCommandSubcommandBuilder()
-  .setName('bot')
-  .setDescription('Get some info about this bot.');
+  .setName("bot")
+  .setDescription("Get some info about this bot.");
 
 const user = new SlashCommandSubcommandBuilder()
-  .setName('user')
-  .setDescription('Get some info about a user.')
+  .setName("user")
+  .setDescription("Get some info about a user.")
   .addUserOption((option) =>
     option
-      .setName('user')
-      .setDescription('The user to get info about.')
+      .setName("user")
+      .setDescription("The user to get info about.")
       .setRequired(true)
   );
 
 const meta = new SlashCommandBuilder()
-  .setName('info')
-  .setDescription('Get some info about various things.')
+  .setName("info")
+  .setDescription("Get some info about various things.")
   .addSubcommand(server)
   .addSubcommand(bot)
   .addSubcommand(user);
@@ -38,11 +37,11 @@ export default command({
     await interaction.deferReply({ ephemeral: true });
 
     switch (interaction.options.getSubcommand()) {
-      case 'server':
+      case "server":
         return await getServerInfo({ interaction, ...ctx });
-      case 'bot':
+      case "bot":
         return await getBotInfo({ interaction, ...ctx });
-      case 'user':
+      case "user":
         return await getUserInfo({ interaction, ...ctx });
     }
   },
@@ -53,41 +52,41 @@ const getServerInfo = async ({ interaction }: CommandContext) => {
   const channels = await interaction.guild?.channels.fetch();
 
   const embed = new EmbedBuilder()
-    .setTitle('Server Info')
+    .setTitle("Server Info")
     .setDescription(`Info about ***${interaction.guild?.name}***`)
     .setColor(COLORS.embed)
     .setThumbnail(interaction.guild?.iconURL() ?? null)
     .setFields([
       {
-        name: 'Guild ID',
-        value: interaction.guildId ?? 'Unknown',
+        name: "Guild ID",
+        value: interaction.guildId ?? "Unknown",
         inline: false,
       },
       {
-        name: 'Owner',
-        value: owner?.user.username ?? 'Unknown',
+        name: "Owner",
+        value: owner?.user.username ?? "Unknown",
         inline: true,
       },
       {
-        name: 'Created',
+        name: "Created",
         value: interaction.guild
           ? formatDate(interaction.guild?.createdAt)
-          : 'Unknown',
+          : "Unknown",
         inline: true,
       },
       {
-        name: 'Members',
-        value: interaction.guild?.memberCount?.toString() ?? 'Unknown',
+        name: "Members",
+        value: interaction.guild?.memberCount?.toString() ?? "Unknown",
         inline: true,
       },
       {
-        name: 'Channels',
-        value: channels?.size?.toString() ?? 'Unknown',
+        name: "Channels",
+        value: channels?.size?.toString() ?? "Unknown",
         inline: true,
       },
       {
-        name: 'Roles',
-        value: interaction.guild?.roles.cache.size?.toString() ?? 'Unknown',
+        name: "Roles",
+        value: interaction.guild?.roles.cache.size?.toString() ?? "Unknown",
         inline: true,
       },
     ]);
@@ -97,24 +96,24 @@ const getServerInfo = async ({ interaction }: CommandContext) => {
 
 const getBotInfo = async ({ interaction }: CommandContext) => {
   const embed = new EmbedBuilder()
-    .setTitle('Bot Info')
+    .setTitle("Bot Info")
     .setDescription(`Info about ***${interaction.client.user?.username}***`)
     .setColor(COLORS.embed)
     .setThumbnail(interaction.client.user?.avatarURL() ?? null)
     .setFields([
       {
-        name: 'Bot ID',
-        value: interaction.client.user?.id ?? 'Unknown',
+        name: "Bot ID",
+        value: interaction.client.user?.id ?? "Unknown",
         inline: false,
       },
       {
-        name: 'Created',
-        value: formatDate(interaction.client.user?.createdAt) ?? 'Unknown',
+        name: "Created",
+        value: formatDate(interaction.client.user?.createdAt) ?? "Unknown",
         inline: true,
       },
       {
-        name: 'Guilds',
-        value: interaction.client.guilds.cache.size?.toString() ?? 'Unknown',
+        name: "Guilds",
+        value: interaction.client.guilds.cache.size?.toString() ?? "Unknown",
         inline: true,
       },
     ]);
@@ -123,30 +122,30 @@ const getBotInfo = async ({ interaction }: CommandContext) => {
 };
 
 const getUserInfo = async ({ interaction }: CommandContext) => {
-  const user = interaction.options.getUser('user', true);
+  const user = interaction.options.getUser("user", true);
   const member = await interaction.guild?.members.fetch(user.id);
-  if (!member) reply.error(interaction, { content: 'User not found' });
+  if (!member) reply.error(interaction, { content: "User not found" });
 
   const embed = new EmbedBuilder()
-    .setTitle('User Info')
+    .setTitle("User Info")
     .setDescription(`Info about ***${user.username}***`)
     .setColor(COLORS.embed)
-    .setThumbnail(user.avatarURL() ?? '')
+    .setThumbnail(user.avatarURL() ?? "")
     .setFields([
       {
-        name: 'User ID',
-        value: user.id ?? 'Unknown',
+        name: "User ID",
+        value: user.id ?? "Unknown",
         inline: false,
       },
       {
-        name: 'Created',
-        value: formatDate(user.createdAt) ?? 'Unknown',
+        name: "Created",
+        value: formatDate(user.createdAt) ?? "Unknown",
         inline: true,
       },
       {
-        name: 'Joined',
+        name: "Joined",
         value:
-          member && member.joinedAt ? formatDate(member.joinedAt) : 'Unknown',
+          member && member.joinedAt ? formatDate(member.joinedAt) : "Unknown",
         inline: true,
       },
     ]);
diff --git a/src/commands/index.ts b/src/commands/index.ts
index 11eba4f..6cfbb89 100644
--- a/src/commands/index.ts
+++ b/src/commands/index.ts
@@ -1,4 +1,4 @@
-import debug from './debug';
-import general from './general';
+import debug from "./debug/index.ts";
+import general from "./general/index.ts";
 
 export default [debug, general];
diff --git a/src/constants/index.ts b/src/constants/index.ts
deleted file mode 100644
index 7c8fff2..0000000
--- a/src/constants/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './namespaces';
-export * from './style';
diff --git a/src/constants/namespaces.ts b/src/constants/namespaces.ts
deleted file mode 100644
index 0bc1deb..0000000
--- a/src/constants/namespaces.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const NAMESPACES = {
-  pagination: 'pagination',
-  help: 'help',
-};
diff --git a/src/constants/style.ts b/src/constants/style.ts
deleted file mode 100644
index c2a4112..0000000
--- a/src/constants/style.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-export const COLORS = {
-  error: '#f54242',
-  warn: '#f5a742',
-  embed: '#2b2d31',
-} as const;
-
-export const EMOJIS = {
-  success: '✅',
-  error: '❌',
-  warn: '⚠️',
-  deny: '🚫',
-  wait: '⏳',
-} as const;
diff --git a/src/env.ts b/src/env.ts
index fee653e..426d0b1 100644
--- a/src/env.ts
+++ b/src/env.ts
@@ -1,10 +1,11 @@
-import { log } from './utils';
+import process from "node:process";
+import { log } from "utils";
 
 const isDev =
-  process.env.NODE_ENV !== 'production' &&
-  process.env.NODE_ENV !== 'PRODUCTION';
+  process.env.NODE_ENV !== "production" &&
+  process.env.NODE_ENV !== "PRODUCTION";
 
-export const ENV = {
+const ENV = {
   /** Whether or not the app is running in the development environment */
   DEV: isDev,
   /**
@@ -15,15 +16,17 @@ export const ENV = {
   BOT_TOKEN:
     (isDev ? process.env.TEST_TOKEN : process.env.BOT_TOKEN) ??
     process.env.BOT_TOKEN ??
-    '',
+    "",
   /** ID of the Discord guild to use for testing */
   TEST_GUILD: process.env.TEST_GUILD ?? null,
 } as const;
 
 // Check to make sure no environment variables are missing
 for (const [key, value] of Object.entries(ENV)) {
-  if (value === undefined || value === '') {
-    log.error('env', `Missing environment variable: ${key}`);
+  if (value === undefined || value === "") {
+    log.error("env", `Missing environment variable: ${key}`);
     process.exit(1);
   }
 }
+
+export default ENV;
diff --git a/src/events/index.ts b/src/events/index.ts
index 901a28e..d61ddfc 100644
--- a/src/events/index.ts
+++ b/src/events/index.ts
@@ -1,5 +1,5 @@
-import ready from './ready';
-import interactionCreate from './interactionCreate';
+import ready from "./ready.ts";
+import interactionCreate from "./interactionCreate/index.ts";
 
 const events = [...interactionCreate, ready];
 
diff --git a/src/events/interactionCreate/commands.ts b/src/events/interactionCreate/commands.ts
index 5543299..52d6846 100644
--- a/src/events/interactionCreate/commands.ts
+++ b/src/events/interactionCreate/commands.ts
@@ -2,10 +2,10 @@ import {
   CommandInteraction,
   GuildMember,
   PermissionFlagsBits,
-} from 'discord.js';
-import categories from '../../commands';
-import { Command, CommandOptions } from '../../types';
-import { event, Logger, reply } from '../../utils';
+} from "discord.js";
+import categories from "commands";
+import { Command, CommandOptions } from "types";
+import { event, Logger, reply } from "utils";
 
 const commands = new Map<string, Command>(
   categories
@@ -16,14 +16,14 @@ const commands = new Map<string, Command>(
 
 const cooldowns = new Map<string, Map<string, number>>();
 
-export default event('interactionCreate', async ({ client }, interaction) => {
+export default event("interactionCreate", async ({ client }, interaction) => {
   if (interaction.isChatInputCommand()) {
     const logger = new Logger(`/${interaction.commandName}`);
     const command = commands.get(interaction.commandName);
 
     if (!command) {
       logger.error(`Command ${interaction.commandName} not found.`);
-      return await reply.error(interaction, 'Command not found.');
+      return await reply.error(interaction, "Command not found.");
     }
 
     const { adminOnly, cooldown } = command.options;
@@ -64,14 +64,14 @@ export default event('interactionCreate', async ({ client }, interaction) => {
 });
 
 const checkCooldown = (
-  cooldown: CommandOptions['cooldown'],
+  cooldown: CommandOptions["cooldown"],
   interaction: CommandInteraction,
   isAdmin: boolean
 ) => {
   if (!cooldown) return null;
 
-  const seconds = typeof cooldown === 'number' ? cooldown : cooldown.seconds;
-  const scope = typeof cooldown === 'number' ? 'user' : cooldown.scope;
+  const seconds = typeof cooldown === "number" ? cooldown : cooldown.seconds;
+  const scope = typeof cooldown === "number" ? "user" : cooldown.scope;
 
   if (!interaction.guildId) return null;
 
@@ -80,7 +80,7 @@ const checkCooldown = (
     cooldowns.get(interaction.commandName) ?? new Map<string, number>();
   const timestamp =
     timestamps.get(
-      scope === 'user' ? interaction.user.id : interaction.guildId
+      scope === "user" ? interaction.user.id : interaction.guildId
     ) ?? 0;
   const cooldownEnd = timestamp + seconds * 1000;
 
@@ -88,7 +88,7 @@ const checkCooldown = (
     return `Command will be available <t:${Math.floor(cooldownEnd / 1000)}:R>.`;
 
   timestamps.set(
-    scope === 'user' ? interaction.user.id : interaction.guildId,
+    scope === "user" ? interaction.user.id : interaction.guildId,
     now
   );
 
diff --git a/src/events/interactionCreate/help.ts b/src/events/interactionCreate/help.ts
index 53f36ab..634c6b9 100644
--- a/src/events/interactionCreate/help.ts
+++ b/src/events/interactionCreate/help.ts
@@ -1,7 +1,6 @@
-import { event, paginationReply, parseId } from '../../utils';
-import { NAMESPACES } from '../../constants';
+import { event, paginationReply, parseId, NAMESPACES } from "utils";
 
-export default event('interactionCreate', async (ctx, interaction) => {
+export default event("interactionCreate", async (ctx, interaction) => {
   if (!interaction.isStringSelectMenu()) return;
   const [namespace] = parseId(interaction.customId);
   if (namespace !== NAMESPACES.help) return;
diff --git a/src/events/interactionCreate/index.ts b/src/events/interactionCreate/index.ts
index 8464d40..cb281e7 100644
--- a/src/events/interactionCreate/index.ts
+++ b/src/events/interactionCreate/index.ts
@@ -1,6 +1,6 @@
-import commands from './commands';
-import help from './help';
-import pagination from './pagination';
+import commands from "./commands.ts";
+import help from "./help.ts";
+import pagination from "./pagination.ts";
 
 const events = [commands, help, pagination];
 
diff --git a/src/events/interactionCreate/pagination.ts b/src/events/interactionCreate/pagination.ts
index 4d6d4d2..5c90d63 100644
--- a/src/events/interactionCreate/pagination.ts
+++ b/src/events/interactionCreate/pagination.ts
@@ -1,7 +1,6 @@
-import { createId, event, generatePage, parseId } from '../../utils';
-import { NAMESPACES } from '../../constants';
+import { createId, event, generatePage, parseId, NAMESPACES } from "utils";
 
-export default event('interactionCreate', async (ctx, interaction) => {
+export default event("interactionCreate", async (ctx, interaction) => {
   if (!interaction.isButton() && !interaction.isStringSelectMenu()) return;
   const [namespace, paginatorName] = parseId(interaction.customId);
   if (namespace !== NAMESPACES.pagination) return;
diff --git a/src/events/ready.ts b/src/events/ready.ts
index e3aac7f..45ae089 100644
--- a/src/events/ready.ts
+++ b/src/events/ready.ts
@@ -1,6 +1,6 @@
-import { event } from '../utils';
+import { event } from "utils";
 
-export default event('ready', ({ logger }, client) => {
+export default event("ready", ({ logger }, client) => {
   logger.system(
     `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!`
   );
diff --git a/src/index.ts b/src/index.ts
index e4aef4a..8a65457 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,6 +1,5 @@
-import 'dotenv/config';
-import client from './client';
-import { registerEvents } from './utils';
-import events from './events';
+import client from "client";
+import { registerEvents } from "utils";
+import events from "./events/index.ts";
 
 registerEvents(client, events);
diff --git a/src/scripts/clear.ts b/src/scripts/clear.ts
index 132f6b2..5ce3351 100644
--- a/src/scripts/clear.ts
+++ b/src/scripts/clear.ts
@@ -1,14 +1,13 @@
-import 'dotenv/config';
-import { REST, Routes, APIUser } from 'discord.js';
-import { ENV } from '../env';
-import { Logger } from '../utils';
+import { REST, Routes, APIUser } from "discord.js";
+import ENV from "env";
+import { Logger } from "utils";
 
-const rest = new REST({ version: '10' }).setToken(ENV.BOT_TOKEN);
-const logger = new Logger('clear');
+const rest = new REST({ version: "10" }).setToken(ENV.BOT_TOKEN);
+const logger = new Logger("clear");
 
 async function main() {
   if (!ENV.TEST_GUILD)
-    throw new Error('Missing environment variable: TEST_GUILD');
+    throw new Error("Missing environment variable: TEST_GUILD");
   const currentUser = (await rest.get(Routes.user())) as APIUser;
 
   await rest.put(Routes.applicationCommands(currentUser.id), { body: [] });
diff --git a/src/scripts/deploy.ts b/src/scripts/deploy.ts
index c6c49c8..2088a51 100644
--- a/src/scripts/deploy.ts
+++ b/src/scripts/deploy.ts
@@ -1,15 +1,14 @@
-import 'dotenv/config';
-import { REST, Routes, APIUser } from 'discord.js';
-import categories from '../commands';
-import { ENV } from '../env';
-import { Logger, extractMeta } from '../utils';
+import { REST, Routes, APIUser } from "discord.js";
+import categories from "commands";
+import ENV from "env";
+import { Logger, extractMeta } from "utils";
 
-const rest = new REST({ version: '10' }).setToken(ENV.BOT_TOKEN);
-const logger = new Logger('deploy');
+const rest = new REST({ version: "10" }).setToken(ENV.BOT_TOKEN);
+const logger = new Logger("deploy");
 
 async function main() {
   if (!ENV.TEST_GUILD)
-    throw new Error('Missing environment variable: TEST_GUILD');
+    throw new Error("Missing environment variable: TEST_GUILD");
   const currentUser = (await rest.get(Routes.user())) as APIUser;
 
   // In development, all commands are deployed to the test guild.
@@ -17,19 +16,19 @@ async function main() {
     await rest.put(
       Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD),
       {
-        body: extractMeta(categories, 'all'),
+        body: extractMeta(categories, "all"),
       }
     );
   // In production, public commmands are deployed globally, and private commands
   // are deployed to the test guild.
   else {
     await rest.put(Routes.applicationCommands(currentUser.id), {
-      body: extractMeta(categories, 'public'),
+      body: extractMeta(categories, "public"),
     });
     await rest.put(
       Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD),
       {
-        body: extractMeta(categories, 'private'),
+        body: extractMeta(categories, "private"),
       }
     );
   }
@@ -42,7 +41,7 @@ main()
     const tag = `${user.username}#${user.discriminator}`;
     logger.system(
       `Commands deployed for \x1b[4m${tag}\x1b[0m\x1b[36m${
-        ENV.DEV ? ` in guild ${ENV.TEST_GUILD}` : ''
+        ENV.DEV ? ` in guild ${ENV.TEST_GUILD}` : ""
       }!`
     );
   })
diff --git a/src/types/commands.ts b/src/types/commands.ts
index 1f45ff3..9b4da0c 100644
--- a/src/types/commands.ts
+++ b/src/types/commands.ts
@@ -6,8 +6,8 @@ import {
   SlashCommandSubcommandsOnlyBuilder,
   AutocompleteInteraction,
   SlashCommandOptionsOnlyBuilder,
-} from 'discord.js';
-import { BaseContext } from './context';
+} from "discord.js";
+import { BaseContext } from "./context.ts";
 
 export interface CommandContext extends BaseContext {
   interaction: ChatInputCommandInteraction;
@@ -52,7 +52,7 @@ export type CommandOptions = {
          *
          * `guild` - The cooldown will be on a per-guild basis.
          */
-        scope?: 'user' | 'guild';
+        scope?: "user" | "guild";
       };
 };
 export type CommandExec = (ctx: CommandContext) => Awaitable<unknown>;
@@ -61,7 +61,7 @@ export type CommandAutocomplete = (
 ) => Awaitable<unknown>;
 export type CommandMeta =
   | SlashCommandBuilder
-  | Omit<SlashCommandBuilder, 'addSubcommand' | 'addSubcommandGroup'>
+  | Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup">
   | SlashCommandSubcommandsOnlyBuilder
   | SlashCommandOptionsOnlyBuilder;
 export interface Command {
diff --git a/src/types/context.ts b/src/types/context.ts
index be64c34..874ff64 100644
--- a/src/types/context.ts
+++ b/src/types/context.ts
@@ -1,5 +1,5 @@
-import { Client } from 'discord.js';
-import { Logger } from '../utils';
+import { Client } from "discord.js";
+import { Logger } from "utils";
 
 export interface BaseContext {
   client: Client;
diff --git a/src/types/events.ts b/src/types/events.ts
index 7af2a15..b4073b5 100644
--- a/src/types/events.ts
+++ b/src/types/events.ts
@@ -1,5 +1,5 @@
-import { ClientEvents, Awaitable } from 'discord.js';
-import { BaseContext } from './context';
+import { ClientEvents, Awaitable } from "discord.js";
+import { BaseContext } from "./context.ts";
 
 export interface EventContext extends BaseContext {}
 
diff --git a/src/types/index.ts b/src/types/index.ts
index ea1f014..7022e85 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,3 +1,3 @@
-export * from './events';
-export * from './commands';
-export * from './pagination';
+export * from "./events.ts";
+export * from "./commands.ts";
+export * from "./pagination.ts";
diff --git a/src/types/pagination.ts b/src/types/pagination.ts
index 3c71ac3..29aa85a 100644
--- a/src/types/pagination.ts
+++ b/src/types/pagination.ts
@@ -1,5 +1,5 @@
-import { APIEmbedField, BaseInteraction } from 'discord.js';
-import { BaseContext } from './context';
+import { APIEmbedField, BaseInteraction } from "discord.js";
+import { BaseContext } from "./context.ts";
 
 export type PaginationData = APIEmbedField[];
 
diff --git a/src/utils/command.ts b/src/utils/command.ts
index 44a5ce0..3ae2249 100644
--- a/src/utils/command.ts
+++ b/src/utils/command.ts
@@ -7,7 +7,7 @@ import {
   CommandExec,
   CommandMeta,
   CommandOptions,
-} from '../types';
+} from "types";
 
 export function command({
   meta,
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
new file mode 100644
index 0000000..b93585d
--- /dev/null
+++ b/src/utils/constants.ts
@@ -0,0 +1,18 @@
+export const COLORS = {
+  error: "#f54242",
+  warn: "#f5a742",
+  embed: "#2b2d31",
+} as const;
+
+export const EMOJIS = {
+  success: "✅",
+  error: "❌",
+  warn: "⚠️",
+  deny: "🚫",
+  wait: "⏳",
+} as const;
+
+export const NAMESPACES = {
+  pagination: "pagination",
+  help: "help",
+} as const;
diff --git a/src/utils/event.ts b/src/utils/event.ts
index 8fe79f6..29956fd 100644
--- a/src/utils/event.ts
+++ b/src/utils/event.ts
@@ -1,7 +1,7 @@
-import { Event, EventExec, EventKeys } from '../types';
-import { Client } from 'discord.js';
-import { Logger } from './logger';
-import { reply } from './replies';
+import { Event, EventExec, EventKeys } from "types";
+import { Client } from "discord.js";
+import { Logger } from "./logger.ts";
+import { reply } from "./replies.ts";
 
 export function event<T extends EventKeys>(
   id: T,
@@ -13,6 +13,7 @@ export function event<T extends EventKeys>(
   };
 }
 
+// deno-lint-ignore no-explicit-any
 export function registerEvents(client: Client, events: Event<any>[]): void {
   for (const event of events)
     client.on(event.id, async (...args) => {
@@ -24,7 +25,7 @@ export function registerEvents(client: Client, events: Event<any>[]): void {
       } catch (error) {
         logger.error(error);
         // If the error is thrown in an interaction, reply to it
-        if (event.id === 'interactionCreate')
+        if (event.id === "interactionCreate")
           reply.error(args[0]).catch(console.error);
       }
     });
diff --git a/src/utils/help.ts b/src/utils/help.ts
index 057f42f..65dd7ff 100644
--- a/src/utils/help.ts
+++ b/src/utils/help.ts
@@ -3,12 +3,12 @@ import {
   BaseInteraction,
   PermissionFlagsBits,
   StringSelectMenuBuilder,
-} from 'discord.js';
-import { NAMESPACES } from '../constants';
-import { createId } from './interaction';
-import categories from '../commands';
-import { ENV } from '../env';
-import { CommandCategoryCommands } from '../types';
+} from "discord.js";
+import { NAMESPACES } from "utils";
+import { createId } from "./interaction.ts";
+import categories from "commands";
+import ENV from "env";
+import { CommandCategoryCommands } from "types";
 
 /**
  * Filters categories to exclude ones that do not contain commands relevant to the user
@@ -27,12 +27,12 @@ const filterCategories = (
 /** Pre-filtered command categories */
 const cats = {
   private: {
-    member: filterCategories('all'),
-    admin: filterCategories('all', true),
+    member: filterCategories("all"),
+    admin: filterCategories("all", true),
   },
   public: {
-    member: filterCategories('public'),
-    admin: filterCategories('public', true),
+    member: filterCategories("public"),
+    admin: filterCategories("public", true),
   },
 };
 
@@ -47,15 +47,15 @@ export const helpSelectComponent = (
   const guildCats =
     interaction.guildId === ENV.TEST_GUILD ? cats.private : cats.public;
 
-  if (guildCats[isAdmin ? 'admin' : 'member'].length === 0) return null;
+  if (guildCats[isAdmin ? "admin" : "member"].length === 0) return null;
 
   return new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
     new StringSelectMenuBuilder()
       .setCustomId(createId(NAMESPACES.help))
-      .setPlaceholder('Select a category...')
+      .setPlaceholder("Select a category...")
       .setMaxValues(1)
       .addOptions(
-        guildCats[isAdmin ? 'admin' : 'member'].map(
+        guildCats[isAdmin ? "admin" : "member"].map(
           ({ name, description, emoji }) => ({
             label: name,
             description,
diff --git a/src/utils/index.ts b/src/utils/index.ts
index d57704b..6588080 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,11 +1,12 @@
-export * from './event';
-export * from './command';
-export * from './replies';
-export * from './chunk';
-export * from './interaction';
-export * from './logger';
-export * from './help';
-export * from './paginators';
-export * from './pagination';
-export * from './split';
-export * from './date';
+export * from "./event.ts";
+export * from "./command.ts";
+export * from "./replies.ts";
+export * from "./chunk.ts";
+export * from "./interaction.ts";
+export * from "./logger.ts";
+export * from "./help.ts";
+export * from "./paginators/index.ts";
+export * from "./pagination.ts";
+export * from "./split.ts";
+export * from "./date.ts";
+export * from "./constants.ts";
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index 88deaad..7876123 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -1,3 +1,4 @@
+import process from "node:process";
 import {
   APIEmbed,
   ActionRowBuilder,
@@ -6,11 +7,11 @@ import {
   EmbedBuilder,
   InteractionReplyOptions,
   StringSelectMenuBuilder,
-} from 'discord.js';
-import { createId } from './interaction';
-import { COLORS, NAMESPACES } from '../constants';
-import { Logger } from './logger';
-import { PaginationContext, PaginationData } from '../types';
+} from "discord.js";
+import { createId } from "./interaction.ts";
+import { COLORS, NAMESPACES } from "utils";
+import { Logger } from "./logger.ts";
+import { PaginationContext, PaginationData } from "types";
 
 export class Paginator {
   name: string;
@@ -19,8 +20,8 @@ export class Paginator {
    * The fields and footer are automatically set by the paginator.
    */
   embedData?:
-    | Omit<APIEmbed, 'fields' | 'footer'>
-    | ((ctx: PaginationContext) => Omit<APIEmbed, 'fields' | 'footer'>);
+    | Omit<APIEmbed, "fields" | "footer">
+    | ((ctx: PaginationContext) => Omit<APIEmbed, "fields" | "footer">);
   /**
    * The reply to which the pagination embed and its controls are added.
    * If not specified, the reply is ephemeral by default.
@@ -31,7 +32,7 @@ export class Paginator {
   /** The number of fields to display on a single page (max 25). */
   pageLength: number;
   /** Asynchronous function to fetch the data for the paginator */
-  getData: (ctx: PaginationContext) => Promise<PaginationData>;
+  getData: (ctx: PaginationContext) => PaginationData | Promise<PaginationData>;
 
   // #region Cache
   /** Whether or not to cache the fetched data */
@@ -93,7 +94,7 @@ export class Paginator {
     // (2 are already being used for back/next buttons and page selector)
     if (
       replyOptions &&
-      typeof replyOptions !== 'function' &&
+      typeof replyOptions !== "function" &&
       replyOptions.components &&
       replyOptions.components.length > 3
     ) {
@@ -105,7 +106,7 @@ export class Paginator {
     // (1 is already being used for the pagination embed)
     if (
       replyOptions &&
-      typeof replyOptions !== 'function' &&
+      typeof replyOptions !== "function" &&
       replyOptions.embeds &&
       replyOptions.embeds.length > 4
     ) {
@@ -176,7 +177,7 @@ export class Paginator {
     const pageCount = Math.ceil(data.length / this.pageLength);
 
     const embedData = this.embedData
-      ? typeof this.embedData === 'function'
+      ? typeof this.embedData === "function"
         ? this.embedData(ctx)
         : this.embedData
       : undefined;
@@ -184,7 +185,7 @@ export class Paginator {
       .setFields(fields)
       .setColor(embedData?.color ?? COLORS.embed);
 
-    if (fields.length === 0) embed.setDescription('No results found!');
+    if (fields.length === 0) embed.setDescription("No results found!");
     else
       embed.setFooter({
         text: `Page ${currentPage} / ${pageCount}`,
@@ -198,7 +199,7 @@ export class Paginator {
     );
     const backButton = new ButtonBuilder()
       .setCustomId(backId)
-      .setLabel('Back')
+      .setLabel("Back")
       .setStyle(ButtonStyle.Primary)
       .setDisabled(offset <= 0);
 
@@ -210,14 +211,14 @@ export class Paginator {
     );
     const nextButton = new ButtonBuilder()
       .setCustomId(nextId)
-      .setLabel('Next')
+      .setLabel("Next")
       .setStyle(ButtonStyle.Primary)
       .setDisabled(currentPage >= pageCount);
 
     const selectId = createId(NAMESPACES.pagination, this.name);
     const pageSelector = new StringSelectMenuBuilder()
       .setCustomId(selectId)
-      .setPlaceholder('Select a page...')
+      .setPlaceholder("Select a page...")
       .setMaxValues(1)
       .setOptions(
         Array.from(Array(pageCount).keys()).map((i) => ({
@@ -236,7 +237,7 @@ export class Paginator {
       );
 
     const replyOptions = this.replyOptions
-      ? typeof this.replyOptions === 'function'
+      ? typeof this.replyOptions === "function"
         ? this.replyOptions(ctx)
         : this.replyOptions
       : undefined;
diff --git a/src/utils/paginators/help.ts b/src/utils/paginators/help.ts
index a74655e..e88402c 100644
--- a/src/utils/paginators/help.ts
+++ b/src/utils/paginators/help.ts
@@ -2,17 +2,17 @@ import {
   APIApplicationCommandOption,
   ApplicationCommandOptionType,
   PermissionFlagsBits,
-} from 'discord.js';
-import categories from '../../commands';
+} from "discord.js";
+import categories from "commands";
 import {
   Command,
   CommandCategoryCommands,
   CommandOptions,
   PaginationData,
-} from '../../types';
-import { helpSelectComponent } from '../help';
-import { Paginator } from '../pagination';
-import { ENV } from '../../env';
+} from "types";
+import { helpSelectComponent } from "../help.ts";
+import { Paginator } from "../pagination.ts";
+import ENV from "env";
 
 /**
  * Extracts subcommands from a command option recursively
@@ -31,8 +31,8 @@ const extractSubcommandsRecursive = (
       name: `/${name} ${option.name}`,
       value: `
       ${option.description}
-      ${cmdOpts.adminOnly ? '🛡️ _admin only_' : ''}${
-        cmdOpts.private ? `${cmdOpts.adminOnly ? '\n' : ''}🔒 _private_` : ''
+      ${cmdOpts.adminOnly ? "🛡️ _admin only_" : ""}${
+        cmdOpts.private ? `${cmdOpts.adminOnly ? "\n" : ""}🔒 _private_` : ""
       }
       `,
     });
@@ -65,10 +65,10 @@ const getCommands = (command: Command): PaginationData => {
       name: `/${command.meta.name}`,
       value: `
       ${command.meta.description}
-      ${command.options.adminOnly ? '🛡️ _admin only_' : ''}${
+      ${command.options.adminOnly ? "🛡️ _admin only_" : ""}${
         command.options.private
-          ? `${command.options.adminOnly ? '\n' : ''}🔒 _private_`
-          : ''
+          ? `${command.options.adminOnly ? "\n" : ""}🔒 _private_`
+          : ""
       }
     `,
     });
@@ -97,15 +97,15 @@ const helpPaginators: Paginator[] =
     // Separate commands into different categories depending on the guild and member that the command is used in/by
     const cmds = {
       private: {
-        member: filterCommands(category.commands, 'all'),
-        admin: filterCommands(category.commands, 'all', true),
+        member: filterCommands(category.commands, "all"),
+        admin: filterCommands(category.commands, "all", true),
       },
       public: {
-        member: filterCommands(category.commands, 'public'),
-        admin: filterCommands(category.commands, 'public', true),
+        member: filterCommands(category.commands, "public"),
+        admin: filterCommands(category.commands, "public", true),
       },
     };
-    const emoji = category.emoji ? `${category.emoji} ` : '';
+    const emoji = category.emoji ? `${category.emoji} ` : "";
 
     return new Paginator(category.name, {
       embedData: {
@@ -113,7 +113,7 @@ const helpPaginators: Paginator[] =
         description:
           category.description ??
           `Browse through ${category.commands.public.length} command${
-            category.commands.public.length > 1 ? 's' : ''
+            category.commands.public.length > 1 ? "s" : ""
           } in ${emoji}${category.name}`,
       },
       replyOptions: ({ interaction }) => {
@@ -123,7 +123,7 @@ const helpPaginators: Paginator[] =
         };
       },
       pageLength: 10,
-      getData: async ({ interaction }) => {
+      getData: ({ interaction }) => {
         const guildCmds =
           interaction.guildId === ENV.TEST_GUILD ? cmds.private : cmds.public;
         if (
diff --git a/src/utils/paginators/index.ts b/src/utils/paginators/index.ts
index e4350fa..0228e2b 100644
--- a/src/utils/paginators/index.ts
+++ b/src/utils/paginators/index.ts
@@ -1,9 +1,9 @@
-import { InteractionReplyOptions } from 'discord.js';
-import { Paginator } from '../pagination';
-import helpPaginators from './help';
-import { createId, parseId } from '../interaction';
-import { NAMESPACES } from '../../constants';
-import { PaginationContext } from '../../types';
+import { InteractionReplyOptions } from "discord.js";
+import { Paginator } from "../pagination.ts";
+import helpPaginators from "./help.ts";
+import { createId, parseId } from "../interaction.ts";
+import { NAMESPACES } from "utils";
+import { PaginationContext } from "types";
 
 // Add new paginators here
 const paginators: Paginator[] = [...helpPaginators /*, otherPaginator */];
@@ -17,7 +17,7 @@ const paginatorMap = new Map<string, Paginator>(
  * @param interactionId The interactionId to generate the page for
  * @returns The generated embed
  */
-export async function generatePage(
+export function generatePage(
   interactionId: string,
   ctx: PaginationContext
 ): Promise<InteractionReplyOptions> {
@@ -29,8 +29,8 @@ export async function generatePage(
 
   let offset = parseInt(offsetString);
   // Page selected from select menu
-  if (offsetString && offsetString.startsWith('select-')) {
-    let targetPage = parseInt(offsetString.split('-')[1]);
+  if (offsetString && offsetString.startsWith("select-")) {
+    let targetPage = parseInt(offsetString.split("-")[1]);
     if (isNaN(targetPage)) targetPage = 0;
     offset = targetPage * paginator.pageLength;
   }
diff --git a/src/utils/replies.ts b/src/utils/replies.ts
index 9660729..93da115 100644
--- a/src/utils/replies.ts
+++ b/src/utils/replies.ts
@@ -2,8 +2,8 @@ import {
   InteractionReplyOptions,
   InteractionEditReplyOptions,
   BaseInteraction,
-} from 'discord.js';
-import { EMOJIS } from '../constants';
+} from "discord.js";
+import { EMOJIS } from "utils";
 
 export interface DeferableInteraction extends BaseInteraction {
   deferred: boolean;
@@ -13,12 +13,12 @@ export interface DeferableInteraction extends BaseInteraction {
 }
 
 export enum ReplyType {
-  Default = 'default',
-  Success = 'success',
-  Error = 'error',
-  Warn = 'warn',
-  Deny = 'deny',
-  Wait = 'wait',
+  Default = "default",
+  Success = "success",
+  Error = "error",
+  Warn = "warn",
+  Deny = "deny",
+  Wait = "wait",
 }
 
 /**
@@ -31,11 +31,11 @@ const getOptions = (
   options: InteractionReplyOptions | string,
   type: ReplyType
 ): InteractionReplyOptions => {
-  if (typeof options === 'string')
+  if (typeof options === "string")
     return getOptions({ content: options }, type);
 
   const { content, ephemeral } = options;
-  const emoji = type === ReplyType.Default ? '' : EMOJIS[type];
+  const emoji = type === ReplyType.Default ? "" : EMOJIS[type];
 
   return {
     ...options,
@@ -57,17 +57,17 @@ export const reply = <T extends DeferableInteraction>(
   type: ReplyType = ReplyType.Default
 ) => {
   if (!interaction.reply || !interaction.editReply)
-    return Promise.reject('Invalid interaction');
+    return Promise.reject("Invalid interaction");
   if (
     !options ||
-    (typeof options === 'object' &&
+    (typeof options === "object" &&
       !options.content &&
       !options.embeds &&
       !options.files)
   )
-    return Promise.reject('Cannot send an empty message');
+    return Promise.reject("Cannot send an empty message");
 
-  if (interaction.replied) return Promise.reject('Interaction already replied');
+  if (interaction.replied) return Promise.reject("Interaction already replied");
 
   const alteredOptions = getOptions(options, type);
   if (interaction.deferred) return interaction.editReply(alteredOptions);
@@ -81,7 +81,7 @@ reply.success = <T extends DeferableInteraction>(
 
 reply.error = <T extends DeferableInteraction>(
   interaction: T,
-  options: InteractionReplyOptions | string = 'Oops. Something went wrong!'
+  options: InteractionReplyOptions | string = "Oops. Something went wrong!"
 ) => reply(interaction, options, ReplyType.Error);
 
 reply.warn = <T extends DeferableInteraction>(
@@ -93,7 +93,7 @@ reply.deny = <T extends DeferableInteraction>(
   interaction: T,
   options:
     | InteractionReplyOptions
-    | string = 'You do not have permission to do that!'
+    | string = "You do not have permission to do that!"
 ) => reply(interaction, options, ReplyType.Deny);
 
 reply.wait = <T extends DeferableInteraction>(
diff --git a/src/utils/split.ts b/src/utils/split.ts
index fea765f..7554c04 100644
--- a/src/utils/split.ts
+++ b/src/utils/split.ts
@@ -1,5 +1,5 @@
-import { CommandInteraction, EmbedBuilder } from 'discord.js';
-import { COLORS } from '../constants';
+import { CommandInteraction, EmbedBuilder } from "discord.js";
+import { COLORS } from "utils";
 
 /** The maximum character length of an embed to send */
 const MAX_EMBED_LENGTH = 2048 as const;
@@ -19,8 +19,10 @@ export async function splitSend(
   title: string,
   msg: string
 ) {
-  if (!interaction.channel) throw new Error('No channel found');
-  if (interaction.replied) throw new Error('Interaction already replied');
+  if (!interaction.channel) throw new Error("No channel found");
+  if (!interaction.channel.isSendable())
+    throw new Error("Channel is not sendable");
+  if (interaction.replied) throw new Error("Interaction already replied");
   if (!interaction.deferred) await interaction.deferReply();
 
   // Split the input into multiple embed descriptions
diff --git a/tsconfig.json b/tsconfig.json
deleted file mode 100644
index 7149c9c..0000000
--- a/tsconfig.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "compilerOptions": {
-    /* Visit https://aka.ms/tsconfig to learn about all posibilities for the tsconfig */
-    "target": "ESNext",
-    "useDefineForClassFields": true,
-    "lib": ["ESNext"],
-    "outDir": "./dist",
-    "allowJs": false,
-    "skipLibCheck": true,
-    "esModuleInterop": true,
-    "allowSyntheticDefaultImports": true,
-    "strict": true,
-    "forceConsistentCasingInFileNames": true,
-    "module": "CommonJS",
-    "moduleResolution": "Node",
-    "resolveJsonModule": true,
-    "isolatedModules": true
-  },
-  "include": ["**/*.ts", "src"],
-  "exclude": ["node_modules", "dist"]
-}

From 83f1ba7afc64c1f7d8d7b71de349849add917fc3 Mon Sep 17 00:00:00 2001
From: Thijn <thijnkroon@gmail.com>
Date: Thu, 7 Nov 2024 13:28:03 +0100
Subject: [PATCH 2/6] chore: run format

---
 .gitignore                                 |   1 +
 deno.json                                  |   6 +-
 src/client/index.ts                        |  10 +-
 src/commands/debug/index.ts                |   8 +-
 src/commands/debug/ping.ts                 |  16 +--
 src/commands/general/help.ts               |  16 +--
 src/commands/general/index.ts              |  14 +--
 src/commands/general/info.ts               |  95 ++++++++--------
 src/commands/index.ts                      |   4 +-
 src/env.ts                                 |  18 ++-
 src/events/index.ts                        |   4 +-
 src/events/interactionCreate/commands.ts   |  41 +++----
 src/events/interactionCreate/help.ts       |   6 +-
 src/events/interactionCreate/index.ts      |   6 +-
 src/events/interactionCreate/pagination.ts |  11 +-
 src/events/ready.ts                        |   6 +-
 src/index.ts                               |   6 +-
 src/scripts/clear.ts                       |  17 +--
 src/scripts/deploy.ts                      |  35 +++---
 src/types/commands.ts                      |  44 ++++----
 src/types/context.ts                       |   4 +-
 src/types/events.ts                        |   4 +-
 src/types/index.ts                         |   6 +-
 src/types/pagination.ts                    |   4 +-
 src/utils/chunk.ts                         |   3 +-
 src/utils/command.ts                       |   6 +-
 src/utils/constants.ts                     |  20 ++--
 src/utils/date.ts                          |   8 +-
 src/utils/event.ts                         |  16 +--
 src/utils/help.ts                          |  44 ++++----
 src/utils/index.ts                         |  24 ++--
 src/utils/logger.ts                        |   4 +-
 src/utils/pagination.ts                    |  67 +++++------
 src/utils/paginators/help.ts               | 122 +++++++++++----------
 src/utils/paginators/index.ts              |  20 ++--
 src/utils/replies.ts                       |  53 ++++-----
 src/utils/split.ts                         |  20 ++--
 37 files changed, 405 insertions(+), 384 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7889494..ef27776 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
 .env
+.prettierrc.json
 
 /.vs/
 /.vscode/
diff --git a/deno.json b/deno.json
index 1a05525..7d40ae0 100644
--- a/deno.json
+++ b/deno.json
@@ -1,12 +1,12 @@
 {
   "tasks": {
-    "dev": "deno run --watch --env-file --allow-net --allow-read src/index.ts",
+    "dev": "deno run --watch --env-file --allow-env --allow-net --allow-read src/index.ts",
     "check": "deno check src/index.ts",
     "lint": "deno lint --fix",
     "fmt": "deno fmt",
     "fmt:check": "deno fmt --check",
-    "deploy": "deno run --env-file --allow-net --allow-read src/scripts/deploy.ts",
-    "clear": "deno run --env-file --allow-net --allow-read src/scripts/clear.ts"
+    "deploy": "deno run --env-file --allow-env --allow-net --allow-read src/scripts/deploy.ts",
+    "clear": "deno run --env-file --allow-env --allow-net --allow-read src/scripts/clear.ts"
   },
   "lint": {
     "include": ["src/"],
diff --git a/src/client/index.ts b/src/client/index.ts
index 61c29d0..5c69f8f 100644
--- a/src/client/index.ts
+++ b/src/client/index.ts
@@ -1,14 +1,14 @@
-import process from "node:process";
-import { Client, GatewayIntentBits } from "discord.js";
-import { log } from "utils";
-import ENV from "env";
+import process from 'node:process';
+import { Client, GatewayIntentBits } from 'discord.js';
+import { log } from 'utils';
+import ENV from 'env';
 
 const client = new Client({
   intents: [GatewayIntentBits.Guilds],
 });
 
 client.login(ENV.BOT_TOKEN).catch((err) => {
-  log.error("login", err);
+  log.error('login', err);
   process.exit(1);
 });
 
diff --git a/src/commands/debug/index.ts b/src/commands/debug/index.ts
index 05c347c..f48e02c 100644
--- a/src/commands/debug/index.ts
+++ b/src/commands/debug/index.ts
@@ -1,7 +1,7 @@
-import { category } from "utils";
-import ping from "./ping.ts";
+import { category } from 'utils';
+import ping from './ping.ts';
 
 export default category(
-  { name: "Debug", description: "Commands used for debugging.", emoji: "🐛" },
-  [ping]
+  { name: 'Debug', description: 'Commands used for debugging.', emoji: '🐛' },
+  [ping],
 );
diff --git a/src/commands/debug/ping.ts b/src/commands/debug/ping.ts
index 2abb65c..94613aa 100644
--- a/src/commands/debug/ping.ts
+++ b/src/commands/debug/ping.ts
@@ -1,13 +1,13 @@
-import { SlashCommandBuilder } from "discord.js";
-import { command, reply } from "utils";
+import { SlashCommandBuilder } from 'discord.js';
+import { command, reply } from 'utils';
 
 const meta = new SlashCommandBuilder()
-  .setName("ping")
-  .setDescription("Ping the bot for a response.")
+  .setName('ping')
+  .setDescription('Ping the bot for a response.')
   .addStringOption((option) =>
     option
-      .setName("message")
-      .setDescription("Provide the bot a message to respond with.")
+      .setName('message')
+      .setDescription('Provide the bot a message to respond with.')
       .setMinLength(1)
       .setMaxLength(2000)
       .setRequired(false)
@@ -17,11 +17,11 @@ export default command({
   meta,
   private: true,
   exec: async ({ client, interaction }) => {
-    const message = interaction.options.getString("message");
+    const message = interaction.options.getString('message');
 
     await reply(interaction, {
       ephemeral: true,
-      content: `${message ?? "Pong!"} (${client.ws.ping}ms)`,
+      content: `${message ?? 'Pong!'} (${client.ws.ping}ms)`,
     });
   },
 });
diff --git a/src/commands/general/help.ts b/src/commands/general/help.ts
index f292c3b..54595d4 100644
--- a/src/commands/general/help.ts
+++ b/src/commands/general/help.ts
@@ -1,25 +1,25 @@
-import { EmbedBuilder, SlashCommandBuilder } from "discord.js";
-import { command, helpSelectComponent, reply } from "utils";
-import { COLORS } from "utils";
+import { EmbedBuilder, SlashCommandBuilder } from 'discord.js';
+import { command, helpSelectComponent, reply } from 'utils';
+import { COLORS } from 'utils';
 
 const meta = new SlashCommandBuilder()
-  .setName("help")
-  .setDescription("Get a list of all commands for the bot.");
+  .setName('help')
+  .setDescription('Get a list of all commands for the bot.');
 
 export default command({
   meta,
   exec: async ({ interaction }) => {
     const embed = new EmbedBuilder()
-      .setTitle("Help Menu")
+      .setTitle('Help Menu')
       .setDescription(
-        "Browse through all available commands by selecting a category below."
+        'Browse through all available commands by selecting a category below.',
       )
       .setColor(COLORS.embed);
 
     const helpSelectMenu = helpSelectComponent(interaction);
     if (!helpSelectMenu) {
       embed.setDescription(
-        "There are no commands available for you to use in this server."
+        'There are no commands available for you to use in this server.',
       );
       return await reply(interaction, {
         embeds: [embed],
diff --git a/src/commands/general/index.ts b/src/commands/general/index.ts
index 53a6e84..f748999 100644
--- a/src/commands/general/index.ts
+++ b/src/commands/general/index.ts
@@ -1,12 +1,12 @@
-import { category } from "utils";
-import help from "./help.ts";
-import info from "./info.ts";
+import { category } from 'utils';
+import help from './help.ts';
+import info from './info.ts';
 
 export default category(
   {
-    name: "General",
-    description: "General bot commands.",
-    emoji: "📖",
+    name: 'General',
+    description: 'General bot commands.',
+    emoji: '📖',
   },
-  [help, info]
+  [help, info],
 );
diff --git a/src/commands/general/info.ts b/src/commands/general/info.ts
index 7153a82..2df712e 100644
--- a/src/commands/general/info.ts
+++ b/src/commands/general/info.ts
@@ -2,31 +2,31 @@ import {
   EmbedBuilder,
   SlashCommandBuilder,
   SlashCommandSubcommandBuilder,
-} from "discord.js";
-import { command, formatDate, reply, COLORS } from "utils";
-import { CommandContext } from "types";
+} from 'discord.js';
+import { COLORS, command, formatDate, reply } from 'utils';
+import { CommandContext } from 'types';
 
 const server = new SlashCommandSubcommandBuilder()
-  .setName("server")
-  .setDescription("Get some info about this server.");
+  .setName('server')
+  .setDescription('Get some info about this server.');
 
 const bot = new SlashCommandSubcommandBuilder()
-  .setName("bot")
-  .setDescription("Get some info about this bot.");
+  .setName('bot')
+  .setDescription('Get some info about this bot.');
 
 const user = new SlashCommandSubcommandBuilder()
-  .setName("user")
-  .setDescription("Get some info about a user.")
+  .setName('user')
+  .setDescription('Get some info about a user.')
   .addUserOption((option) =>
     option
-      .setName("user")
-      .setDescription("The user to get info about.")
+      .setName('user')
+      .setDescription('The user to get info about.')
       .setRequired(true)
   );
 
 const meta = new SlashCommandBuilder()
-  .setName("info")
-  .setDescription("Get some info about various things.")
+  .setName('info')
+  .setDescription('Get some info about various things.')
   .addSubcommand(server)
   .addSubcommand(bot)
   .addSubcommand(user);
@@ -37,11 +37,11 @@ export default command({
     await interaction.deferReply({ ephemeral: true });
 
     switch (interaction.options.getSubcommand()) {
-      case "server":
+      case 'server':
         return await getServerInfo({ interaction, ...ctx });
-      case "bot":
+      case 'bot':
         return await getBotInfo({ interaction, ...ctx });
-      case "user":
+      case 'user':
         return await getUserInfo({ interaction, ...ctx });
     }
   },
@@ -52,41 +52,41 @@ const getServerInfo = async ({ interaction }: CommandContext) => {
   const channels = await interaction.guild?.channels.fetch();
 
   const embed = new EmbedBuilder()
-    .setTitle("Server Info")
+    .setTitle('Server Info')
     .setDescription(`Info about ***${interaction.guild?.name}***`)
     .setColor(COLORS.embed)
     .setThumbnail(interaction.guild?.iconURL() ?? null)
     .setFields([
       {
-        name: "Guild ID",
-        value: interaction.guildId ?? "Unknown",
+        name: 'Guild ID',
+        value: interaction.guildId ?? 'Unknown',
         inline: false,
       },
       {
-        name: "Owner",
-        value: owner?.user.username ?? "Unknown",
+        name: 'Owner',
+        value: owner?.user.username ?? 'Unknown',
         inline: true,
       },
       {
-        name: "Created",
+        name: 'Created',
         value: interaction.guild
           ? formatDate(interaction.guild?.createdAt)
-          : "Unknown",
+          : 'Unknown',
         inline: true,
       },
       {
-        name: "Members",
-        value: interaction.guild?.memberCount?.toString() ?? "Unknown",
+        name: 'Members',
+        value: interaction.guild?.memberCount?.toString() ?? 'Unknown',
         inline: true,
       },
       {
-        name: "Channels",
-        value: channels?.size?.toString() ?? "Unknown",
+        name: 'Channels',
+        value: channels?.size?.toString() ?? 'Unknown',
         inline: true,
       },
       {
-        name: "Roles",
-        value: interaction.guild?.roles.cache.size?.toString() ?? "Unknown",
+        name: 'Roles',
+        value: interaction.guild?.roles.cache.size?.toString() ?? 'Unknown',
         inline: true,
       },
     ]);
@@ -96,24 +96,24 @@ const getServerInfo = async ({ interaction }: CommandContext) => {
 
 const getBotInfo = async ({ interaction }: CommandContext) => {
   const embed = new EmbedBuilder()
-    .setTitle("Bot Info")
+    .setTitle('Bot Info')
     .setDescription(`Info about ***${interaction.client.user?.username}***`)
     .setColor(COLORS.embed)
     .setThumbnail(interaction.client.user?.avatarURL() ?? null)
     .setFields([
       {
-        name: "Bot ID",
-        value: interaction.client.user?.id ?? "Unknown",
+        name: 'Bot ID',
+        value: interaction.client.user?.id ?? 'Unknown',
         inline: false,
       },
       {
-        name: "Created",
-        value: formatDate(interaction.client.user?.createdAt) ?? "Unknown",
+        name: 'Created',
+        value: formatDate(interaction.client.user?.createdAt) ?? 'Unknown',
         inline: true,
       },
       {
-        name: "Guilds",
-        value: interaction.client.guilds.cache.size?.toString() ?? "Unknown",
+        name: 'Guilds',
+        value: interaction.client.guilds.cache.size?.toString() ?? 'Unknown',
         inline: true,
       },
     ]);
@@ -122,30 +122,31 @@ const getBotInfo = async ({ interaction }: CommandContext) => {
 };
 
 const getUserInfo = async ({ interaction }: CommandContext) => {
-  const user = interaction.options.getUser("user", true);
+  const user = interaction.options.getUser('user', true);
   const member = await interaction.guild?.members.fetch(user.id);
-  if (!member) reply.error(interaction, { content: "User not found" });
+  if (!member) reply.error(interaction, { content: 'User not found' });
 
   const embed = new EmbedBuilder()
-    .setTitle("User Info")
+    .setTitle('User Info')
     .setDescription(`Info about ***${user.username}***`)
     .setColor(COLORS.embed)
-    .setThumbnail(user.avatarURL() ?? "")
+    .setThumbnail(user.avatarURL() ?? '')
     .setFields([
       {
-        name: "User ID",
-        value: user.id ?? "Unknown",
+        name: 'User ID',
+        value: user.id ?? 'Unknown',
         inline: false,
       },
       {
-        name: "Created",
-        value: formatDate(user.createdAt) ?? "Unknown",
+        name: 'Created',
+        value: formatDate(user.createdAt) ?? 'Unknown',
         inline: true,
       },
       {
-        name: "Joined",
-        value:
-          member && member.joinedAt ? formatDate(member.joinedAt) : "Unknown",
+        name: 'Joined',
+        value: member && member.joinedAt
+          ? formatDate(member.joinedAt)
+          : 'Unknown',
         inline: true,
       },
     ]);
diff --git a/src/commands/index.ts b/src/commands/index.ts
index 6cfbb89..1854824 100644
--- a/src/commands/index.ts
+++ b/src/commands/index.ts
@@ -1,4 +1,4 @@
-import debug from "./debug/index.ts";
-import general from "./general/index.ts";
+import debug from './debug/index.ts';
+import general from './general/index.ts';
 
 export default [debug, general];
diff --git a/src/env.ts b/src/env.ts
index 426d0b1..392fbcb 100644
--- a/src/env.ts
+++ b/src/env.ts
@@ -1,9 +1,8 @@
-import process from "node:process";
-import { log } from "utils";
+import process from 'node:process';
+import { log } from 'utils';
 
-const isDev =
-  process.env.NODE_ENV !== "production" &&
-  process.env.NODE_ENV !== "PRODUCTION";
+const isDev = process.env.NODE_ENV !== 'production' &&
+  process.env.NODE_ENV !== 'PRODUCTION';
 
 const ENV = {
   /** Whether or not the app is running in the development environment */
@@ -13,18 +12,17 @@ const ENV = {
    *
    * If `DEV` is true, the `TEST_TOKEN` environment variable will be used instead (if it exists, otherwise `BOT_TOKEN` will still be used).
    */
-  BOT_TOKEN:
-    (isDev ? process.env.TEST_TOKEN : process.env.BOT_TOKEN) ??
+  BOT_TOKEN: (isDev ? process.env.TEST_TOKEN : process.env.BOT_TOKEN) ??
     process.env.BOT_TOKEN ??
-    "",
+    '',
   /** ID of the Discord guild to use for testing */
   TEST_GUILD: process.env.TEST_GUILD ?? null,
 } as const;
 
 // Check to make sure no environment variables are missing
 for (const [key, value] of Object.entries(ENV)) {
-  if (value === undefined || value === "") {
-    log.error("env", `Missing environment variable: ${key}`);
+  if (value === undefined || value === '') {
+    log.error('env', `Missing environment variable: ${key}`);
     process.exit(1);
   }
 }
diff --git a/src/events/index.ts b/src/events/index.ts
index d61ddfc..5b9ae6e 100644
--- a/src/events/index.ts
+++ b/src/events/index.ts
@@ -1,5 +1,5 @@
-import ready from "./ready.ts";
-import interactionCreate from "./interactionCreate/index.ts";
+import ready from './ready.ts';
+import interactionCreate from './interactionCreate/index.ts';
 
 const events = [...interactionCreate, ready];
 
diff --git a/src/events/interactionCreate/commands.ts b/src/events/interactionCreate/commands.ts
index 52d6846..41d63af 100644
--- a/src/events/interactionCreate/commands.ts
+++ b/src/events/interactionCreate/commands.ts
@@ -2,33 +2,33 @@ import {
   CommandInteraction,
   GuildMember,
   PermissionFlagsBits,
-} from "discord.js";
-import categories from "commands";
-import { Command, CommandOptions } from "types";
-import { event, Logger, reply } from "utils";
+} from 'discord.js';
+import categories from 'commands';
+import { Command, CommandOptions } from 'types';
+import { event, Logger, reply } from 'utils';
 
 const commands = new Map<string, Command>(
   categories
     .map(({ commands }) => commands.all)
     .flat()
-    .map((c) => [c.meta.name, c])
+    .map((c) => [c.meta.name, c]),
 );
 
 const cooldowns = new Map<string, Map<string, number>>();
 
-export default event("interactionCreate", async ({ client }, interaction) => {
+export default event('interactionCreate', async ({ client }, interaction) => {
   if (interaction.isChatInputCommand()) {
     const logger = new Logger(`/${interaction.commandName}`);
     const command = commands.get(interaction.commandName);
 
     if (!command) {
       logger.error(`Command ${interaction.commandName} not found.`);
-      return await reply.error(interaction, "Command not found.");
+      return await reply.error(interaction, 'Command not found.');
     }
 
     const { adminOnly, cooldown } = command.options;
     const isAdmin = (interaction.member as GuildMember).permissions.has(
-      PermissionFlagsBits.Administrator
+      PermissionFlagsBits.Administrator,
     );
 
     // If the command is marked as adminOnly, check if the user is an admin
@@ -47,13 +47,15 @@ export default event("interactionCreate", async ({ client }, interaction) => {
     const logger = new Logger(`/${interaction.commandName}`);
     const command = commands.get(interaction.commandName);
 
-    if (!command)
+    if (!command) {
       return logger.error(`Command ${interaction.commandName} not found.`);
+    }
 
-    if (!command.autocomplete)
+    if (!command.autocomplete) {
       return logger.error(
-        `Missing autocomplete handler for ${interaction.commandName}.`
+        `Missing autocomplete handler for ${interaction.commandName}.`,
       );
+    }
 
     await command.autocomplete({
       client,
@@ -64,14 +66,14 @@ export default event("interactionCreate", async ({ client }, interaction) => {
 });
 
 const checkCooldown = (
-  cooldown: CommandOptions["cooldown"],
+  cooldown: CommandOptions['cooldown'],
   interaction: CommandInteraction,
-  isAdmin: boolean
+  isAdmin: boolean,
 ) => {
   if (!cooldown) return null;
 
-  const seconds = typeof cooldown === "number" ? cooldown : cooldown.seconds;
-  const scope = typeof cooldown === "number" ? "user" : cooldown.scope;
+  const seconds = typeof cooldown === 'number' ? cooldown : cooldown.seconds;
+  const scope = typeof cooldown === 'number' ? 'user' : cooldown.scope;
 
   if (!interaction.guildId) return null;
 
@@ -80,16 +82,17 @@ const checkCooldown = (
     cooldowns.get(interaction.commandName) ?? new Map<string, number>();
   const timestamp =
     timestamps.get(
-      scope === "user" ? interaction.user.id : interaction.guildId
+      scope === 'user' ? interaction.user.id : interaction.guildId,
     ) ?? 0;
   const cooldownEnd = timestamp + seconds * 1000;
 
-  if (now < cooldownEnd && !isAdmin)
+  if (now < cooldownEnd && !isAdmin) {
     return `Command will be available <t:${Math.floor(cooldownEnd / 1000)}:R>.`;
+  }
 
   timestamps.set(
-    scope === "user" ? interaction.user.id : interaction.guildId,
-    now
+    scope === 'user' ? interaction.user.id : interaction.guildId,
+    now,
   );
 
   cooldowns.set(interaction.commandName, timestamps);
diff --git a/src/events/interactionCreate/help.ts b/src/events/interactionCreate/help.ts
index 634c6b9..1117cb2 100644
--- a/src/events/interactionCreate/help.ts
+++ b/src/events/interactionCreate/help.ts
@@ -1,6 +1,6 @@
-import { event, paginationReply, parseId, NAMESPACES } from "utils";
+import { event, NAMESPACES, paginationReply, parseId } from 'utils';
 
-export default event("interactionCreate", async (ctx, interaction) => {
+export default event('interactionCreate', async (ctx, interaction) => {
   if (!interaction.isStringSelectMenu()) return;
   const [namespace] = parseId(interaction.customId);
   if (namespace !== NAMESPACES.help) return;
@@ -10,6 +10,6 @@ export default event("interactionCreate", async (ctx, interaction) => {
     await paginationReply(interaction.values[0], {
       ...ctx,
       interaction,
-    })
+    }),
   );
 });
diff --git a/src/events/interactionCreate/index.ts b/src/events/interactionCreate/index.ts
index cb281e7..e3f0d20 100644
--- a/src/events/interactionCreate/index.ts
+++ b/src/events/interactionCreate/index.ts
@@ -1,6 +1,6 @@
-import commands from "./commands.ts";
-import help from "./help.ts";
-import pagination from "./pagination.ts";
+import commands from './commands.ts';
+import help from './help.ts';
+import pagination from './pagination.ts';
 
 const events = [commands, help, pagination];
 
diff --git a/src/events/interactionCreate/pagination.ts b/src/events/interactionCreate/pagination.ts
index 5c90d63..b9b9418 100644
--- a/src/events/interactionCreate/pagination.ts
+++ b/src/events/interactionCreate/pagination.ts
@@ -1,20 +1,21 @@
-import { createId, event, generatePage, parseId, NAMESPACES } from "utils";
+import { createId, event, generatePage, NAMESPACES, parseId } from 'utils';
 
-export default event("interactionCreate", async (ctx, interaction) => {
+export default event('interactionCreate', async (ctx, interaction) => {
   if (!interaction.isButton() && !interaction.isStringSelectMenu()) return;
   const [namespace, paginatorName] = parseId(interaction.customId);
   if (namespace !== NAMESPACES.pagination) return;
 
   await interaction.deferUpdate();
   let interactionId = interaction.customId;
-  if (interaction.isStringSelectMenu())
+  if (interaction.isStringSelectMenu()) {
     interactionId = createId(
       namespace,
       paginatorName,
-      `select-${interaction.values[0]}`
+      `select-${interaction.values[0]}`,
     );
+  }
 
   return await interaction.editReply(
-    await generatePage(interactionId, { ...ctx, interaction })
+    await generatePage(interactionId, { ...ctx, interaction }),
   );
 });
diff --git a/src/events/ready.ts b/src/events/ready.ts
index 45ae089..f672033 100644
--- a/src/events/ready.ts
+++ b/src/events/ready.ts
@@ -1,7 +1,7 @@
-import { event } from "utils";
+import { event } from 'utils';
 
-export default event("ready", ({ logger }, client) => {
+export default event('ready', ({ logger }, client) => {
   logger.system(
-    `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!`
+    `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!`,
   );
 });
diff --git a/src/index.ts b/src/index.ts
index 8a65457..256e401 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,5 @@
-import client from "client";
-import { registerEvents } from "utils";
-import events from "./events/index.ts";
+import client from 'client';
+import { registerEvents } from 'utils';
+import events from './events/index.ts';
 
 registerEvents(client, events);
diff --git a/src/scripts/clear.ts b/src/scripts/clear.ts
index 5ce3351..e00a68d 100644
--- a/src/scripts/clear.ts
+++ b/src/scripts/clear.ts
@@ -1,19 +1,20 @@
-import { REST, Routes, APIUser } from "discord.js";
-import ENV from "env";
-import { Logger } from "utils";
+import { APIUser, REST, Routes } from 'discord.js';
+import ENV from 'env';
+import { Logger } from 'utils';
 
-const rest = new REST({ version: "10" }).setToken(ENV.BOT_TOKEN);
-const logger = new Logger("clear");
+const rest = new REST({ version: '10' }).setToken(ENV.BOT_TOKEN);
+const logger = new Logger('clear');
 
 async function main() {
-  if (!ENV.TEST_GUILD)
-    throw new Error("Missing environment variable: TEST_GUILD");
+  if (!ENV.TEST_GUILD) {
+    throw new Error('Missing environment variable: TEST_GUILD');
+  }
   const currentUser = (await rest.get(Routes.user())) as APIUser;
 
   await rest.put(Routes.applicationCommands(currentUser.id), { body: [] });
   await rest.put(
     Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD),
-    { body: [] }
+    { body: [] },
   );
 
   return currentUser;
diff --git a/src/scripts/deploy.ts b/src/scripts/deploy.ts
index 2088a51..b1b5707 100644
--- a/src/scripts/deploy.ts
+++ b/src/scripts/deploy.ts
@@ -1,35 +1,36 @@
-import { REST, Routes, APIUser } from "discord.js";
-import categories from "commands";
-import ENV from "env";
-import { Logger, extractMeta } from "utils";
+import { APIUser, REST, Routes } from 'discord.js';
+import categories from 'commands';
+import ENV from 'env';
+import { extractMeta, Logger } from 'utils';
 
-const rest = new REST({ version: "10" }).setToken(ENV.BOT_TOKEN);
-const logger = new Logger("deploy");
+const rest = new REST({ version: '10' }).setToken(ENV.BOT_TOKEN);
+const logger = new Logger('deploy');
 
 async function main() {
-  if (!ENV.TEST_GUILD)
-    throw new Error("Missing environment variable: TEST_GUILD");
+  if (!ENV.TEST_GUILD) {
+    throw new Error('Missing environment variable: TEST_GUILD');
+  }
   const currentUser = (await rest.get(Routes.user())) as APIUser;
 
   // In development, all commands are deployed to the test guild.
-  if (ENV.DEV)
+  if (ENV.DEV) {
     await rest.put(
       Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD),
       {
-        body: extractMeta(categories, "all"),
-      }
+        body: extractMeta(categories, 'all'),
+      },
     );
-  // In production, public commmands are deployed globally, and private commands
+  } // In production, public commmands are deployed globally, and private commands
   // are deployed to the test guild.
   else {
     await rest.put(Routes.applicationCommands(currentUser.id), {
-      body: extractMeta(categories, "public"),
+      body: extractMeta(categories, 'public'),
     });
     await rest.put(
       Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD),
       {
-        body: extractMeta(categories, "private"),
-      }
+        body: extractMeta(categories, 'private'),
+      },
     );
   }
 
@@ -41,8 +42,8 @@ main()
     const tag = `${user.username}#${user.discriminator}`;
     logger.system(
       `Commands deployed for \x1b[4m${tag}\x1b[0m\x1b[36m${
-        ENV.DEV ? ` in guild ${ENV.TEST_GUILD}` : ""
-      }!`
+        ENV.DEV ? ` in guild ${ENV.TEST_GUILD}` : ''
+      }!`,
     );
   })
   .catch((e) => logger.error(e));
diff --git a/src/types/commands.ts b/src/types/commands.ts
index 9b4da0c..f615018 100644
--- a/src/types/commands.ts
+++ b/src/types/commands.ts
@@ -1,13 +1,13 @@
 import {
+  APIEmbedField,
+  AutocompleteInteraction,
   Awaitable,
   ChatInputCommandInteraction,
   SlashCommandBuilder,
-  APIEmbedField,
-  SlashCommandSubcommandsOnlyBuilder,
-  AutocompleteInteraction,
   SlashCommandOptionsOnlyBuilder,
-} from "discord.js";
-import { BaseContext } from "./context.ts";
+  SlashCommandSubcommandsOnlyBuilder,
+} from 'discord.js';
+import { BaseContext } from './context.ts';
 
 export interface CommandContext extends BaseContext {
   interaction: ChatInputCommandInteraction;
@@ -39,29 +39,29 @@ export type CommandOptions = {
   cooldown?:
     | number
     | {
-        /**
-         * The number of seconds this command will be on cooldown for.
-         */
-        seconds: number;
-        /**
-         * The scope of the cooldown.
-         * @default user
-         *
-         * @values
-         * `user` - The cooldown will be on a per-user basis.
-         *
-         * `guild` - The cooldown will be on a per-guild basis.
-         */
-        scope?: "user" | "guild";
-      };
+      /**
+       * The number of seconds this command will be on cooldown for.
+       */
+      seconds: number;
+      /**
+       * The scope of the cooldown.
+       * @default user
+       *
+       * @values
+       * `user` - The cooldown will be on a per-user basis.
+       *
+       * `guild` - The cooldown will be on a per-guild basis.
+       */
+      scope?: 'user' | 'guild';
+    };
 };
 export type CommandExec = (ctx: CommandContext) => Awaitable<unknown>;
 export type CommandAutocomplete = (
-  ctx: AutocompleteContext
+  ctx: AutocompleteContext,
 ) => Awaitable<unknown>;
 export type CommandMeta =
   | SlashCommandBuilder
-  | Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup">
+  | Omit<SlashCommandBuilder, 'addSubcommand' | 'addSubcommandGroup'>
   | SlashCommandSubcommandsOnlyBuilder
   | SlashCommandOptionsOnlyBuilder;
 export interface Command {
diff --git a/src/types/context.ts b/src/types/context.ts
index 874ff64..5c3e2ff 100644
--- a/src/types/context.ts
+++ b/src/types/context.ts
@@ -1,5 +1,5 @@
-import { Client } from "discord.js";
-import { Logger } from "utils";
+import { Client } from 'discord.js';
+import { Logger } from 'utils';
 
 export interface BaseContext {
   client: Client;
diff --git a/src/types/events.ts b/src/types/events.ts
index b4073b5..97151c8 100644
--- a/src/types/events.ts
+++ b/src/types/events.ts
@@ -1,5 +1,5 @@
-import { ClientEvents, Awaitable } from "discord.js";
-import { BaseContext } from "./context.ts";
+import { Awaitable, ClientEvents } from 'discord.js';
+import { BaseContext } from './context.ts';
 
 export interface EventContext extends BaseContext {}
 
diff --git a/src/types/index.ts b/src/types/index.ts
index 7022e85..402425f 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,3 +1,3 @@
-export * from "./events.ts";
-export * from "./commands.ts";
-export * from "./pagination.ts";
+export * from './events.ts';
+export * from './commands.ts';
+export * from './pagination.ts';
diff --git a/src/types/pagination.ts b/src/types/pagination.ts
index 29aa85a..310265b 100644
--- a/src/types/pagination.ts
+++ b/src/types/pagination.ts
@@ -1,5 +1,5 @@
-import { APIEmbedField, BaseInteraction } from "discord.js";
-import { BaseContext } from "./context.ts";
+import { APIEmbedField, BaseInteraction } from 'discord.js';
+import { BaseContext } from './context.ts';
 
 export type PaginationData = APIEmbedField[];
 
diff --git a/src/utils/chunk.ts b/src/utils/chunk.ts
index 6a12ef1..f93df62 100644
--- a/src/utils/chunk.ts
+++ b/src/utils/chunk.ts
@@ -8,8 +8,9 @@
 export function chunk<T>(items: T[], chunk: number): T[][] {
   const chunks: T[][] = [];
 
-  for (let i = 0; i < items.length; i += chunk)
+  for (let i = 0; i < items.length; i += chunk) {
     chunks.push(items.slice(i, i + chunk));
+  }
 
   return chunks;
 }
diff --git a/src/utils/command.ts b/src/utils/command.ts
index 3ae2249..e58ad22 100644
--- a/src/utils/command.ts
+++ b/src/utils/command.ts
@@ -7,7 +7,7 @@ import {
   CommandExec,
   CommandMeta,
   CommandOptions,
-} from "types";
+} from 'types';
 
 export function command({
   meta,
@@ -29,7 +29,7 @@ export function command({
 
 export function category(
   metadata: CommandCategoryMetadata,
-  commands: Command[]
+  commands: Command[],
 ): CommandCategory {
   return {
     ...metadata,
@@ -49,7 +49,7 @@ export function category(
  */
 export function extractMeta(
   categories: CommandCategory[],
-  type: keyof CommandCategoryCommands
+  type: keyof CommandCategoryCommands,
 ) {
   return categories.flatMap(({ commands }) =>
     commands[type].map(({ meta }) => meta)
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index b93585d..4ce1892 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -1,18 +1,18 @@
 export const COLORS = {
-  error: "#f54242",
-  warn: "#f5a742",
-  embed: "#2b2d31",
+  error: '#f54242',
+  warn: '#f5a742',
+  embed: '#2b2d31',
 } as const;
 
 export const EMOJIS = {
-  success: "✅",
-  error: "❌",
-  warn: "⚠️",
-  deny: "🚫",
-  wait: "⏳",
+  success: '✅',
+  error: '❌',
+  warn: '⚠️',
+  deny: '🚫',
+  wait: '⏳',
 } as const;
 
 export const NAMESPACES = {
-  pagination: "pagination",
-  help: "help",
+  pagination: 'pagination',
+  help: 'help',
 } as const;
diff --git a/src/utils/date.ts b/src/utils/date.ts
index e3393ac..044f03d 100644
--- a/src/utils/date.ts
+++ b/src/utils/date.ts
@@ -5,6 +5,8 @@
  * @note This is very basic and only supports the format `dd/mm/yyyy`, for more in-depth formatting, it is recommneded to use a library such as [date-fns](https://date-fns.org/)
  */
 export const formatDate = (date: Date) =>
-  `${date.getDate().toString().padStart(2, '0')}/${(date.getMonth() + 1)
-    .toString()
-    .padStart(2, '0')}/${date.getFullYear()}`;
+  `${date.getDate().toString().padStart(2, '0')}/${
+    (date.getMonth() + 1)
+      .toString()
+      .padStart(2, '0')
+  }/${date.getFullYear()}`;
diff --git a/src/utils/event.ts b/src/utils/event.ts
index 29956fd..2993467 100644
--- a/src/utils/event.ts
+++ b/src/utils/event.ts
@@ -1,11 +1,11 @@
-import { Event, EventExec, EventKeys } from "types";
-import { Client } from "discord.js";
-import { Logger } from "./logger.ts";
-import { reply } from "./replies.ts";
+import { Event, EventExec, EventKeys } from 'types';
+import { Client } from 'discord.js';
+import { Logger } from './logger.ts';
+import { reply } from './replies.ts';
 
 export function event<T extends EventKeys>(
   id: T,
-  exec: EventExec<T>
+  exec: EventExec<T>,
 ): Event<T> {
   return {
     id,
@@ -15,7 +15,7 @@ export function event<T extends EventKeys>(
 
 // deno-lint-ignore no-explicit-any
 export function registerEvents(client: Client, events: Event<any>[]): void {
-  for (const event of events)
+  for (const event of events) {
     client.on(event.id, async (...args) => {
       const logger = new Logger(event.id);
 
@@ -25,8 +25,10 @@ export function registerEvents(client: Client, events: Event<any>[]): void {
       } catch (error) {
         logger.error(error);
         // If the error is thrown in an interaction, reply to it
-        if (event.id === "interactionCreate")
+        if (event.id === 'interactionCreate') {
           reply.error(args[0]).catch(console.error);
+        }
       }
     });
+  }
 }
diff --git a/src/utils/help.ts b/src/utils/help.ts
index 65dd7ff..9d0e59d 100644
--- a/src/utils/help.ts
+++ b/src/utils/help.ts
@@ -3,12 +3,12 @@ import {
   BaseInteraction,
   PermissionFlagsBits,
   StringSelectMenuBuilder,
-} from "discord.js";
-import { NAMESPACES } from "utils";
-import { createId } from "./interaction.ts";
-import categories from "commands";
-import ENV from "env";
-import { CommandCategoryCommands } from "types";
+} from 'discord.js';
+import { NAMESPACES } from 'utils';
+import { createId } from './interaction.ts';
+import categories from 'commands';
+import ENV from 'env';
+import { CommandCategoryCommands } from 'types';
 
 /**
  * Filters categories to exclude ones that do not contain commands relevant to the user
@@ -18,7 +18,7 @@ import { CommandCategoryCommands } from "types";
  */
 const filterCategories = (
   cmdType: keyof CommandCategoryCommands,
-  isAdmin = false
+  isAdmin = false,
 ) =>
   categories?.filter((c) =>
     c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin)
@@ -27,42 +27,42 @@ const filterCategories = (
 /** Pre-filtered command categories */
 const cats = {
   private: {
-    member: filterCategories("all"),
-    admin: filterCategories("all", true),
+    member: filterCategories('all'),
+    admin: filterCategories('all', true),
   },
   public: {
-    member: filterCategories("public"),
-    admin: filterCategories("public", true),
+    member: filterCategories('public'),
+    admin: filterCategories('public', true),
   },
 };
 
 /** Select menu for the help embed */
 export const helpSelectComponent = (
-  interaction: BaseInteraction
+  interaction: BaseInteraction,
 ): ActionRowBuilder<StringSelectMenuBuilder> | null => {
-  const isAdmin =
-    interaction.memberPermissions &&
+  const isAdmin = interaction.memberPermissions &&
     interaction.memberPermissions.has(PermissionFlagsBits.Administrator);
   // Categories specific to this guild (test guild or not)
-  const guildCats =
-    interaction.guildId === ENV.TEST_GUILD ? cats.private : cats.public;
+  const guildCats = interaction.guildId === ENV.TEST_GUILD
+    ? cats.private
+    : cats.public;
 
-  if (guildCats[isAdmin ? "admin" : "member"].length === 0) return null;
+  if (guildCats[isAdmin ? 'admin' : 'member'].length === 0) return null;
 
   return new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
     new StringSelectMenuBuilder()
       .setCustomId(createId(NAMESPACES.help))
-      .setPlaceholder("Select a category...")
+      .setPlaceholder('Select a category...')
       .setMaxValues(1)
       .addOptions(
-        guildCats[isAdmin ? "admin" : "member"].map(
+        guildCats[isAdmin ? 'admin' : 'member'].map(
           ({ name, description, emoji }) => ({
             label: name,
             description,
             emoji,
             value: name,
-          })
-        )
-      )
+          }),
+        ),
+      ),
   );
 };
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 6588080..b0f17b3 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,12 +1,12 @@
-export * from "./event.ts";
-export * from "./command.ts";
-export * from "./replies.ts";
-export * from "./chunk.ts";
-export * from "./interaction.ts";
-export * from "./logger.ts";
-export * from "./help.ts";
-export * from "./paginators/index.ts";
-export * from "./pagination.ts";
-export * from "./split.ts";
-export * from "./date.ts";
-export * from "./constants.ts";
+export * from './event.ts';
+export * from './command.ts';
+export * from './replies.ts';
+export * from './chunk.ts';
+export * from './interaction.ts';
+export * from './logger.ts';
+export * from './help.ts';
+export * from './paginators/index.ts';
+export * from './pagination.ts';
+export * from './split.ts';
+export * from './date.ts';
+export * from './constants.ts';
diff --git a/src/utils/logger.ts b/src/utils/logger.ts
index d0e4de1..93fb4ee 100644
--- a/src/utils/logger.ts
+++ b/src/utils/logger.ts
@@ -74,11 +74,11 @@ export class Logger {
 export const log = (
   category: string,
   message: unknown,
-  type: LogType = LogType.Default
+  type: LogType = LogType.Default,
 ) =>
   console.log(
     getTextColor(type),
-    `[${type}] ${category.toLowerCase()} - ${message}`
+    `[${type}] ${category.toLowerCase()} - ${message}`,
   );
 
 log.error = (category: string, message: unknown) =>
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index 7876123..b6b385f 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -1,17 +1,17 @@
-import process from "node:process";
+import process from 'node:process';
 import {
-  APIEmbed,
   ActionRowBuilder,
+  APIEmbed,
   ButtonBuilder,
   ButtonStyle,
   EmbedBuilder,
   InteractionReplyOptions,
   StringSelectMenuBuilder,
-} from "discord.js";
-import { createId } from "./interaction.ts";
-import { COLORS, NAMESPACES } from "utils";
-import { Logger } from "./logger.ts";
-import { PaginationContext, PaginationData } from "types";
+} from 'discord.js';
+import { createId } from './interaction.ts';
+import { COLORS, NAMESPACES } from 'utils';
+import { Logger } from './logger.ts';
+import { PaginationContext, PaginationData } from 'types';
 
 export class Paginator {
   name: string;
@@ -20,8 +20,8 @@ export class Paginator {
    * The fields and footer are automatically set by the paginator.
    */
   embedData?:
-    | Omit<APIEmbed, "fields" | "footer">
-    | ((ctx: PaginationContext) => Omit<APIEmbed, "fields" | "footer">);
+    | Omit<APIEmbed, 'fields' | 'footer'>
+    | ((ctx: PaginationContext) => Omit<APIEmbed, 'fields' | 'footer'>);
   /**
    * The reply to which the pagination embed and its controls are added.
    * If not specified, the reply is ephemeral by default.
@@ -78,14 +78,14 @@ export class Paginator {
        * (ctx) => `${ctx.interaction.user.id}-${ctx.interaction.guildId}`
        */
       getCacheKey?: typeof Paginator.prototype.getCacheKey;
-    }
+    },
   ) {
     this.logger = new Logger(`paginators/${name}`);
 
     // Page length can be at most 25 due to limit of 25 fields per embed
     if (pageLength > 25) {
       this.logger.error(
-        `Paginator "${name}" has a page length greater than 25`
+        `Paginator "${name}" has a page length greater than 25`,
       );
       process.exit(1);
     }
@@ -94,7 +94,7 @@ export class Paginator {
     // (2 are already being used for back/next buttons and page selector)
     if (
       replyOptions &&
-      typeof replyOptions !== "function" &&
+      typeof replyOptions !== 'function' &&
       replyOptions.components &&
       replyOptions.components.length > 3
     ) {
@@ -106,7 +106,7 @@ export class Paginator {
     // (1 is already being used for the pagination embed)
     if (
       replyOptions &&
-      typeof replyOptions !== "function" &&
+      typeof replyOptions !== 'function' &&
       replyOptions.embeds &&
       replyOptions.embeds.length > 4
     ) {
@@ -117,7 +117,7 @@ export class Paginator {
     // If caching is enabled, the cache key function must be specified
     if (cacheData && !getCacheKey) {
       this.logger.error(
-        `Paginator "${name}" has caching enabled but no cache key function specified`
+        `Paginator "${name}" has caching enabled but no cache key function specified`,
       );
       process.exit(1);
     }
@@ -138,7 +138,7 @@ export class Paginator {
    */
   public async getPage(
     offset: number,
-    ctx: PaginationContext
+    ctx: PaginationContext,
   ): Promise<InteractionReplyOptions> {
     // If caching is enabled, try to get the data from the cache and fetch otherwise
     const cacheKey = this.getCacheKey(ctx);
@@ -170,14 +170,14 @@ export class Paginator {
   protected formatPage(
     offset: number,
     data: PaginationData,
-    ctx: PaginationContext
+    ctx: PaginationContext,
   ): InteractionReplyOptions {
     const fields = data.slice(offset, offset + this.pageLength);
     const currentPage = Math.floor(offset / this.pageLength) + 1;
     const pageCount = Math.ceil(data.length / this.pageLength);
 
     const embedData = this.embedData
-      ? typeof this.embedData === "function"
+      ? typeof this.embedData === 'function'
         ? this.embedData(ctx)
         : this.embedData
       : undefined;
@@ -185,21 +185,22 @@ export class Paginator {
       .setFields(fields)
       .setColor(embedData?.color ?? COLORS.embed);
 
-    if (fields.length === 0) embed.setDescription("No results found!");
-    else
+    if (fields.length === 0) embed.setDescription('No results found!');
+    else {
       embed.setFooter({
         text: `Page ${currentPage} / ${pageCount}`,
       });
+    }
 
     // Back button
     const backId = createId(
       NAMESPACES.pagination,
       this.name,
-      offset - this.pageLength
+      offset - this.pageLength,
     );
     const backButton = new ButtonBuilder()
       .setCustomId(backId)
-      .setLabel("Back")
+      .setLabel('Back')
       .setStyle(ButtonStyle.Primary)
       .setDisabled(offset <= 0);
 
@@ -207,45 +208,47 @@ export class Paginator {
     const nextId = createId(
       NAMESPACES.pagination,
       this.name,
-      offset + this.pageLength
+      offset + this.pageLength,
     );
     const nextButton = new ButtonBuilder()
       .setCustomId(nextId)
-      .setLabel("Next")
+      .setLabel('Next')
       .setStyle(ButtonStyle.Primary)
       .setDisabled(currentPage >= pageCount);
 
     const selectId = createId(NAMESPACES.pagination, this.name);
     const pageSelector = new StringSelectMenuBuilder()
       .setCustomId(selectId)
-      .setPlaceholder("Select a page...")
+      .setPlaceholder('Select a page...')
       .setMaxValues(1)
       .setOptions(
         Array.from(Array(pageCount).keys()).map((i) => ({
           label: `Page ${i + 1}`,
           value: i.toString(),
-        }))
+        })),
       );
 
     const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
       backButton,
-      nextButton
+      nextButton,
     );
-    const selectMenu =
-      new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
-        pageSelector
+    const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>()
+      .addComponents(
+        pageSelector,
       );
 
     const replyOptions = this.replyOptions
-      ? typeof this.replyOptions === "function"
+      ? typeof this.replyOptions === 'function'
         ? this.replyOptions(ctx)
         : this.replyOptions
       : undefined;
 
-    if (replyOptions?.components && replyOptions.components.length > 3)
+    if (replyOptions?.components && replyOptions.components.length > 3) {
       throw new Error(`Paginator "${this.name}" has more than 3 components`);
-    if (replyOptions?.embeds && replyOptions.embeds.length > 4)
+    }
+    if (replyOptions?.embeds && replyOptions.embeds.length > 4) {
       throw new Error(`Paginator "${this.name}" has more than 4 embeds`);
+    }
 
     return {
       ...this.replyOptions,
diff --git a/src/utils/paginators/help.ts b/src/utils/paginators/help.ts
index e88402c..fd4a645 100644
--- a/src/utils/paginators/help.ts
+++ b/src/utils/paginators/help.ts
@@ -2,17 +2,17 @@ import {
   APIApplicationCommandOption,
   ApplicationCommandOptionType,
   PermissionFlagsBits,
-} from "discord.js";
-import categories from "commands";
+} from 'discord.js';
+import categories from 'commands';
 import {
   Command,
   CommandCategoryCommands,
   CommandOptions,
   PaginationData,
-} from "types";
-import { helpSelectComponent } from "../help.ts";
-import { Paginator } from "../pagination.ts";
-import ENV from "env";
+} from 'types';
+import { helpSelectComponent } from '../help.ts';
+import { Paginator } from '../pagination.ts';
+import ENV from 'env';
 
 /**
  * Extracts subcommands from a command option recursively
@@ -23,25 +23,26 @@ import ENV from "env";
 const extractSubcommandsRecursive = (
   option: APIApplicationCommandOption,
   name: string,
-  cmdOpts: CommandOptions
+  cmdOpts: CommandOptions,
 ): PaginationData => {
   const result: PaginationData = [];
-  if (option.type === ApplicationCommandOptionType.Subcommand)
+  if (option.type === ApplicationCommandOptionType.Subcommand) {
     result.push({
       name: `/${name} ${option.name}`,
       value: `
       ${option.description}
-      ${cmdOpts.adminOnly ? "🛡️ _admin only_" : ""}${
-        cmdOpts.private ? `${cmdOpts.adminOnly ? "\n" : ""}🔒 _private_` : ""
+      ${cmdOpts.adminOnly ? '🛡️ _admin only_' : ''}${
+        cmdOpts.private ? `${cmdOpts.adminOnly ? '\n' : ''}🔒 _private_` : ''
       }
       `,
     });
-  else if (option.type === ApplicationCommandOptionType.SubcommandGroup)
+  } else if (option.type === ApplicationCommandOptionType.SubcommandGroup) {
     option.options?.forEach((sub) =>
       result.push(
-        ...extractSubcommandsRecursive(sub, `${name} ${option.name}`, cmdOpts)
+        ...extractSubcommandsRecursive(sub, `${name} ${option.name}`, cmdOpts),
       )
     );
+  }
   return result;
 };
 
@@ -55,23 +56,24 @@ const getCommands = (command: Command): PaginationData => {
     extractSubcommandsRecursive(
       option.toJSON(),
       command.meta.name,
-      command.options
+      command.options,
     )
   );
 
   // If no subcommands are found, this command is a standalone command
-  if (result.length === 0)
+  if (result.length === 0) {
     result.push({
       name: `/${command.meta.name}`,
       value: `
       ${command.meta.description}
-      ${command.options.adminOnly ? "🛡️ _admin only_" : ""}${
+      ${command.options.adminOnly ? '🛡️ _admin only_' : ''}${
         command.options.private
-          ? `${command.options.adminOnly ? "\n" : ""}🔒 _private_`
-          : ""
+          ? `${command.options.adminOnly ? '\n' : ''}🔒 _private_`
+          : ''
       }
     `,
     });
+  }
   return result;
 };
 
@@ -85,55 +87,55 @@ const getCommands = (command: Command): PaginationData => {
 const filterCommands = (
   commands: CommandCategoryCommands,
   type: keyof CommandCategoryCommands,
-  isAdmin = false
+  isAdmin = false,
 ) =>
   commands[type]
     .sort((a, b) => a.meta.name.localeCompare(b.meta.name))
     .filter((c) => !c.options.adminOnly || isAdmin)
     .flatMap((c) => getCommands(c));
 
-const helpPaginators: Paginator[] =
-  categories?.map((category) => {
-    // Separate commands into different categories depending on the guild and member that the command is used in/by
-    const cmds = {
-      private: {
-        member: filterCommands(category.commands, "all"),
-        admin: filterCommands(category.commands, "all", true),
-      },
-      public: {
-        member: filterCommands(category.commands, "public"),
-        admin: filterCommands(category.commands, "public", true),
-      },
-    };
-    const emoji = category.emoji ? `${category.emoji} ` : "";
+const helpPaginators: Paginator[] = categories?.map((category) => {
+  // Separate commands into different categories depending on the guild and member that the command is used in/by
+  const cmds = {
+    private: {
+      member: filterCommands(category.commands, 'all'),
+      admin: filterCommands(category.commands, 'all', true),
+    },
+    public: {
+      member: filterCommands(category.commands, 'public'),
+      admin: filterCommands(category.commands, 'public', true),
+    },
+  };
+  const emoji = category.emoji ? `${category.emoji} ` : '';
 
-    return new Paginator(category.name, {
-      embedData: {
-        title: `${emoji}${category.name} Commands`,
-        description:
-          category.description ??
-          `Browse through ${category.commands.public.length} command${
-            category.commands.public.length > 1 ? "s" : ""
-          } in ${emoji}${category.name}`,
-      },
-      replyOptions: ({ interaction }) => {
-        const helpSelectMenu = helpSelectComponent(interaction);
-        return {
-          components: helpSelectMenu ? [helpSelectMenu] : [],
-        };
-      },
-      pageLength: 10,
-      getData: ({ interaction }) => {
-        const guildCmds =
-          interaction.guildId === ENV.TEST_GUILD ? cmds.private : cmds.public;
-        if (
-          interaction.memberPermissions &&
-          interaction.memberPermissions.has(PermissionFlagsBits.Administrator)
-        )
-          return guildCmds.admin;
-        return guildCmds.member;
-      },
-    });
-  }) ?? [];
+  return new Paginator(category.name, {
+    embedData: {
+      title: `${emoji}${category.name} Commands`,
+      description: category.description ??
+        `Browse through ${category.commands.public.length} command${
+          category.commands.public.length > 1 ? 's' : ''
+        } in ${emoji}${category.name}`,
+    },
+    replyOptions: ({ interaction }) => {
+      const helpSelectMenu = helpSelectComponent(interaction);
+      return {
+        components: helpSelectMenu ? [helpSelectMenu] : [],
+      };
+    },
+    pageLength: 10,
+    getData: ({ interaction }) => {
+      const guildCmds = interaction.guildId === ENV.TEST_GUILD
+        ? cmds.private
+        : cmds.public;
+      if (
+        interaction.memberPermissions &&
+        interaction.memberPermissions.has(PermissionFlagsBits.Administrator)
+      ) {
+        return guildCmds.admin;
+      }
+      return guildCmds.member;
+    },
+  });
+}) ?? [];
 
 export default helpPaginators;
diff --git a/src/utils/paginators/index.ts b/src/utils/paginators/index.ts
index 0228e2b..8196cbd 100644
--- a/src/utils/paginators/index.ts
+++ b/src/utils/paginators/index.ts
@@ -1,15 +1,15 @@
-import { InteractionReplyOptions } from "discord.js";
-import { Paginator } from "../pagination.ts";
-import helpPaginators from "./help.ts";
-import { createId, parseId } from "../interaction.ts";
-import { NAMESPACES } from "utils";
-import { PaginationContext } from "types";
+import { InteractionReplyOptions } from 'discord.js';
+import { Paginator } from '../pagination.ts';
+import helpPaginators from './help.ts';
+import { createId, parseId } from '../interaction.ts';
+import { NAMESPACES } from 'utils';
+import { PaginationContext } from 'types';
 
 // Add new paginators here
 const paginators: Paginator[] = [...helpPaginators /*, otherPaginator */];
 
 const paginatorMap = new Map<string, Paginator>(
-  paginators.map((p) => [p.name, p])
+  paginators.map((p) => [p.name, p]),
 );
 
 /**
@@ -19,7 +19,7 @@ const paginatorMap = new Map<string, Paginator>(
  */
 export function generatePage(
   interactionId: string,
-  ctx: PaginationContext
+  ctx: PaginationContext,
 ): Promise<InteractionReplyOptions> {
   // Extract metadata from interactionId
   const [_namespace, paginatorName, offsetString] = parseId(interactionId);
@@ -29,8 +29,8 @@ export function generatePage(
 
   let offset = parseInt(offsetString);
   // Page selected from select menu
-  if (offsetString && offsetString.startsWith("select-")) {
-    let targetPage = parseInt(offsetString.split("-")[1]);
+  if (offsetString && offsetString.startsWith('select-')) {
+    let targetPage = parseInt(offsetString.split('-')[1]);
     if (isNaN(targetPage)) targetPage = 0;
     offset = targetPage * paginator.pageLength;
   }
diff --git a/src/utils/replies.ts b/src/utils/replies.ts
index 93da115..0505984 100644
--- a/src/utils/replies.ts
+++ b/src/utils/replies.ts
@@ -1,9 +1,9 @@
 import {
-  InteractionReplyOptions,
-  InteractionEditReplyOptions,
   BaseInteraction,
-} from "discord.js";
-import { EMOJIS } from "utils";
+  InteractionEditReplyOptions,
+  InteractionReplyOptions,
+} from 'discord.js';
+import { EMOJIS } from 'utils';
 
 export interface DeferableInteraction extends BaseInteraction {
   deferred: boolean;
@@ -13,12 +13,12 @@ export interface DeferableInteraction extends BaseInteraction {
 }
 
 export enum ReplyType {
-  Default = "default",
-  Success = "success",
-  Error = "error",
-  Warn = "warn",
-  Deny = "deny",
-  Wait = "wait",
+  Default = 'default',
+  Success = 'success',
+  Error = 'error',
+  Warn = 'warn',
+  Deny = 'deny',
+  Wait = 'wait',
 }
 
 /**
@@ -29,13 +29,14 @@ export enum ReplyType {
  */
 const getOptions = (
   options: InteractionReplyOptions | string,
-  type: ReplyType
+  type: ReplyType,
 ): InteractionReplyOptions => {
-  if (typeof options === "string")
+  if (typeof options === 'string') {
     return getOptions({ content: options }, type);
+  }
 
   const { content, ephemeral } = options;
-  const emoji = type === ReplyType.Default ? "" : EMOJIS[type];
+  const emoji = type === ReplyType.Default ? '' : EMOJIS[type];
 
   return {
     ...options,
@@ -54,20 +55,22 @@ const getOptions = (
 export const reply = <T extends DeferableInteraction>(
   interaction: T,
   options: InteractionReplyOptions | string,
-  type: ReplyType = ReplyType.Default
+  type: ReplyType = ReplyType.Default,
 ) => {
-  if (!interaction.reply || !interaction.editReply)
-    return Promise.reject("Invalid interaction");
+  if (!interaction.reply || !interaction.editReply) {
+    return Promise.reject('Invalid interaction');
+  }
   if (
     !options ||
-    (typeof options === "object" &&
+    (typeof options === 'object' &&
       !options.content &&
       !options.embeds &&
       !options.files)
-  )
-    return Promise.reject("Cannot send an empty message");
+  ) {
+    return Promise.reject('Cannot send an empty message');
+  }
 
-  if (interaction.replied) return Promise.reject("Interaction already replied");
+  if (interaction.replied) return Promise.reject('Interaction already replied');
 
   const alteredOptions = getOptions(options, type);
   if (interaction.deferred) return interaction.editReply(alteredOptions);
@@ -76,27 +79,27 @@ export const reply = <T extends DeferableInteraction>(
 
 reply.success = <T extends DeferableInteraction>(
   interaction: T,
-  options: InteractionReplyOptions | string
+  options: InteractionReplyOptions | string,
 ) => reply(interaction, options, ReplyType.Success);
 
 reply.error = <T extends DeferableInteraction>(
   interaction: T,
-  options: InteractionReplyOptions | string = "Oops. Something went wrong!"
+  options: InteractionReplyOptions | string = 'Oops. Something went wrong!',
 ) => reply(interaction, options, ReplyType.Error);
 
 reply.warn = <T extends DeferableInteraction>(
   interaction: T,
-  options: InteractionReplyOptions | string
+  options: InteractionReplyOptions | string,
 ) => reply(interaction, options, ReplyType.Warn);
 
 reply.deny = <T extends DeferableInteraction>(
   interaction: T,
   options:
     | InteractionReplyOptions
-    | string = "You do not have permission to do that!"
+    | string = 'You do not have permission to do that!',
 ) => reply(interaction, options, ReplyType.Deny);
 
 reply.wait = <T extends DeferableInteraction>(
   interaction: T,
-  options: InteractionReplyOptions | string
+  options: InteractionReplyOptions | string,
 ) => reply(interaction, options, ReplyType.Wait);
diff --git a/src/utils/split.ts b/src/utils/split.ts
index 7554c04..88eb349 100644
--- a/src/utils/split.ts
+++ b/src/utils/split.ts
@@ -1,5 +1,5 @@
-import { CommandInteraction, EmbedBuilder } from "discord.js";
-import { COLORS } from "utils";
+import { CommandInteraction, EmbedBuilder } from 'discord.js';
+import { COLORS } from 'utils';
 
 /** The maximum character length of an embed to send */
 const MAX_EMBED_LENGTH = 2048 as const;
@@ -17,12 +17,13 @@ export async function splitSend(
   input: string[],
   seperator: string,
   title: string,
-  msg: string
+  msg: string,
 ) {
-  if (!interaction.channel) throw new Error("No channel found");
-  if (!interaction.channel.isSendable())
-    throw new Error("Channel is not sendable");
-  if (interaction.replied) throw new Error("Interaction already replied");
+  if (!interaction.channel) throw new Error('No channel found');
+  if (!interaction.channel.isSendable()) {
+    throw new Error('Channel is not sendable');
+  }
+  if (interaction.replied) throw new Error('Interaction already replied');
   if (!interaction.deferred) await interaction.deferReply();
 
   // Split the input into multiple embed descriptions
@@ -48,7 +49,7 @@ export async function splitSend(
       .setTitle(
         `${title} ${
           descriptions.length > 1 ? `(${i + 1}/${descriptions.length})` : ``
-        }`
+        }`,
       )
       .setDescription(description);
     messageEmbeds[index].push(embed);
@@ -62,6 +63,7 @@ export async function splitSend(
         .send({ embeds: messageEmbeds[i] })
         .catch(console.log);
     }
-  } else
+  } else {
     await interaction.editReply({ embeds: messageEmbeds[0], content: msg });
+  }
 }

From 3559aead01cbed56bac4f07f6b66819ec8b1eb37 Mon Sep 17 00:00:00 2001
From: Thijn <thijnkroon@gmail.com>
Date: Thu, 7 Nov 2024 14:19:18 +0100
Subject: [PATCH 3/6] fix: resolve import conflicts

---
 src/index.ts                  |  3 +-
 src/utils/help.ts             | 56 +++++++++++++---------
 src/utils/pagination.ts       |  5 +-
 src/utils/paginators/help.ts  | 89 ++++++++++++++++++-----------------
 src/utils/paginators/index.ts |  8 +++-
 5 files changed, 90 insertions(+), 71 deletions(-)

diff --git a/src/index.ts b/src/index.ts
index 256e401..f23ac85 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,6 @@
 import client from 'client';
-import { registerEvents } from 'utils';
+import { initPaginators, registerEvents } from 'utils';
 import events from './events/index.ts';
 
 registerEvents(client, events);
+initPaginators();
diff --git a/src/utils/help.ts b/src/utils/help.ts
index 9d0e59d..a6baff9 100644
--- a/src/utils/help.ts
+++ b/src/utils/help.ts
@@ -8,7 +8,7 @@ import { NAMESPACES } from 'utils';
 import { createId } from './interaction.ts';
 import categories from 'commands';
 import ENV from 'env';
-import { CommandCategoryCommands } from 'types';
+import { CommandCategory, CommandCategoryCommands } from 'types';
 
 /**
  * Filters categories to exclude ones that do not contain commands relevant to the user
@@ -21,33 +21,47 @@ const filterCategories = (
   isAdmin = false,
 ) =>
   categories?.filter((c) =>
-    c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin)
+    c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin),
   );
 
-/** Pre-filtered command categories */
-const cats = {
+/** Cached filtered command categories */
+// deno-lint-ignore prefer-const
+let cats = {
   private: {
-    member: filterCategories('all'),
-    admin: filterCategories('all', true),
+    member: null as null | CommandCategory[],
+    admin: null as null | CommandCategory[],
   },
   public: {
-    member: filterCategories('public'),
-    admin: filterCategories('public', true),
+    member: null as null | CommandCategory[],
+    admin: null as null | CommandCategory[],
   },
 };
+const getCategories = (
+  scope: 'private' | 'public',
+  access: 'admin' | 'member',
+) => {
+  if (!cats[scope][access])
+    cats[scope][access] = filterCategories(
+      scope === 'private' ? 'all' : 'public',
+      access === 'admin',
+    );
+  return cats[scope][access];
+};
 
 /** Select menu for the help embed */
 export const helpSelectComponent = (
   interaction: BaseInteraction,
 ): ActionRowBuilder<StringSelectMenuBuilder> | null => {
-  const isAdmin = interaction.memberPermissions &&
+  const isAdmin =
+    interaction.memberPermissions &&
     interaction.memberPermissions.has(PermissionFlagsBits.Administrator);
-  // Categories specific to this guild (test guild or not)
-  const guildCats = interaction.guildId === ENV.TEST_GUILD
-    ? cats.private
-    : cats.public;
 
-  if (guildCats[isAdmin ? 'admin' : 'member'].length === 0) return null;
+  // Categories specific to this guild (test guild or not)
+  const guildCats = getCategories(
+    interaction.guildId === ENV.TEST_GUILD ? 'private' : 'public',
+    isAdmin ? 'admin' : 'member',
+  );
+  if (guildCats.length === 0) return null;
 
   return new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
     new StringSelectMenuBuilder()
@@ -55,14 +69,12 @@ export const helpSelectComponent = (
       .setPlaceholder('Select a category...')
       .setMaxValues(1)
       .addOptions(
-        guildCats[isAdmin ? 'admin' : 'member'].map(
-          ({ name, description, emoji }) => ({
-            label: name,
-            description,
-            emoji,
-            value: name,
-          }),
-        ),
+        guildCats.map(({ name, description, emoji }) => ({
+          label: name,
+          description,
+          emoji,
+          value: name,
+        })),
       ),
   );
 };
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index b6b385f..119a7bf 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -143,7 +143,6 @@ export class Paginator {
     // If caching is enabled, try to get the data from the cache and fetch otherwise
     const cacheKey = this.getCacheKey(ctx);
     if (this.cacheData && this.cachedData.has(cacheKey)) {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
       return this.formatPage(offset, this.cachedData.get(cacheKey)!, ctx);
     }
 
@@ -232,8 +231,8 @@ export class Paginator {
       backButton,
       nextButton,
     );
-    const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>()
-      .addComponents(
+    const selectMenu =
+      new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
         pageSelector,
       );
 
diff --git a/src/utils/paginators/help.ts b/src/utils/paginators/help.ts
index fd4a645..dc427d8 100644
--- a/src/utils/paginators/help.ts
+++ b/src/utils/paginators/help.ts
@@ -40,7 +40,7 @@ const extractSubcommandsRecursive = (
     option.options?.forEach((sub) =>
       result.push(
         ...extractSubcommandsRecursive(sub, `${name} ${option.name}`, cmdOpts),
-      )
+      ),
     );
   }
   return result;
@@ -57,7 +57,7 @@ const getCommands = (command: Command): PaginationData => {
       option.toJSON(),
       command.meta.name,
       command.options,
-    )
+    ),
   );
 
   // If no subcommands are found, this command is a standalone command
@@ -94,48 +94,49 @@ const filterCommands = (
     .filter((c) => !c.options.adminOnly || isAdmin)
     .flatMap((c) => getCommands(c));
 
-const helpPaginators: Paginator[] = categories?.map((category) => {
-  // Separate commands into different categories depending on the guild and member that the command is used in/by
-  const cmds = {
-    private: {
-      member: filterCommands(category.commands, 'all'),
-      admin: filterCommands(category.commands, 'all', true),
-    },
-    public: {
-      member: filterCommands(category.commands, 'public'),
-      admin: filterCommands(category.commands, 'public', true),
-    },
-  };
-  const emoji = category.emoji ? `${category.emoji} ` : '';
+const helpPaginators = () =>
+  categories?.map((category) => {
+    // Separate commands into different categories depending on the guild and member that the command is used in/by
+    const cmds = {
+      private: {
+        member: filterCommands(category.commands, 'all'),
+        admin: filterCommands(category.commands, 'all', true),
+      },
+      public: {
+        member: filterCommands(category.commands, 'public'),
+        admin: filterCommands(category.commands, 'public', true),
+      },
+    };
+    const emoji = category.emoji ? `${category.emoji} ` : '';
 
-  return new Paginator(category.name, {
-    embedData: {
-      title: `${emoji}${category.name} Commands`,
-      description: category.description ??
-        `Browse through ${category.commands.public.length} command${
-          category.commands.public.length > 1 ? 's' : ''
-        } in ${emoji}${category.name}`,
-    },
-    replyOptions: ({ interaction }) => {
-      const helpSelectMenu = helpSelectComponent(interaction);
-      return {
-        components: helpSelectMenu ? [helpSelectMenu] : [],
-      };
-    },
-    pageLength: 10,
-    getData: ({ interaction }) => {
-      const guildCmds = interaction.guildId === ENV.TEST_GUILD
-        ? cmds.private
-        : cmds.public;
-      if (
-        interaction.memberPermissions &&
-        interaction.memberPermissions.has(PermissionFlagsBits.Administrator)
-      ) {
-        return guildCmds.admin;
-      }
-      return guildCmds.member;
-    },
-  });
-}) ?? [];
+    return new Paginator(category.name, {
+      embedData: {
+        title: `${emoji}${category.name} Commands`,
+        description:
+          category.description ??
+          `Browse through ${category.commands.public.length} command${
+            category.commands.public.length > 1 ? 's' : ''
+          } in ${emoji}${category.name}`,
+      },
+      replyOptions: ({ interaction }) => {
+        const helpSelectMenu = helpSelectComponent(interaction);
+        return {
+          components: helpSelectMenu ? [helpSelectMenu] : [],
+        };
+      },
+      pageLength: 10,
+      getData: ({ interaction }) => {
+        const guildCmds =
+          interaction.guildId === ENV.TEST_GUILD ? cmds.private : cmds.public;
+        if (
+          interaction.memberPermissions &&
+          interaction.memberPermissions.has(PermissionFlagsBits.Administrator)
+        ) {
+          return guildCmds.admin;
+        }
+        return guildCmds.member;
+      },
+    });
+  }) ?? [];
 
 export default helpPaginators;
diff --git a/src/utils/paginators/index.ts b/src/utils/paginators/index.ts
index 8196cbd..12bc10a 100644
--- a/src/utils/paginators/index.ts
+++ b/src/utils/paginators/index.ts
@@ -6,12 +6,18 @@ import { NAMESPACES } from 'utils';
 import { PaginationContext } from 'types';
 
 // Add new paginators here
-const paginators: Paginator[] = [...helpPaginators /*, otherPaginator */];
+// If they need to be initialized, add them to the initPaginators function
+const paginators: Paginator[] = [];
 
 const paginatorMap = new Map<string, Paginator>(
   paginators.map((p) => [p.name, p]),
 );
 
+export function initPaginators() {
+  for (const paginator of helpPaginators())
+    paginatorMap.set(paginator.name, paginator);
+}
+
 /**
  * Generate the embed for a specific page of a paginator
  * @param interactionId The interactionId to generate the page for

From e2762c582aedf1851e16c950349452aaa06fd3e1 Mon Sep 17 00:00:00 2001
From: Thijn <thijnkroon@gmail.com>
Date: Sat, 9 Nov 2024 09:54:10 +0100
Subject: [PATCH 4/6] docs: update README for deno

---
 README.md | 51 +++++++++++++++++++++++++++++++--------------------
 1 file changed, 31 insertions(+), 20 deletions(-)

diff --git a/README.md b/README.md
index 5a36983..457ed1b 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
 # Discord bot template
 
-[![discord.js](https://img.shields.io/github/package-json/dependency-version/ThijnK/discord-bot-template-ts/discord.js)](https://discord.js.org/)
+[![discord.js](https://img.shields.io/badge/discord.js-%5E14.16.3-blue)](https://discord.js.org/)
 [![Stars](https://img.shields.io/github/stars/ThijnK/discord-bot-template-ts)](https://github.com/ThijnK/discord-bot-template-ts/stargazers)
 [![Contributors](https://img.shields.io/github/contributors/ThijnK/discord-bot-template-ts)](https://github.com/ThijnK/discord-bot-template-ts/graphs/contributors)
 [![GitHub release](https://img.shields.io/github/v/release/ThijnK/discord-bot-template-ts?label=version)](https://github.com/ThijnK/discord-bot-template-ts/releases)
-[![Build](https://img.shields.io/github/actions/workflow/status/ThijnK/discord-bot-template-ts/build.yml)](https://github.com/ThijnK/discord-bot-template-ts/actions)
+[![Checks](https://img.shields.io/github/actions/workflow/status/ThijnK/discord-bot-template-ts/check.yml?label=checks)](https://github.com/ThijnK/discord-bot-template-ts/actions)
 [![License](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
 
-A _TypeScript_ template for a **Discord bot**, using the [discord.js](https://discord.js.org/) library.
+A _TypeScript_ template for a **Discord bot**, now powered by **Deno**!
 
 ## Features
 
@@ -25,8 +25,7 @@ A _TypeScript_ template for a **Discord bot**, using the [discord.js](https://di
 
 Some knowledge of TypeScript and Discord.js is recommended, and you'll need the following installed:
 
-- [Node.js](https://nodejs.org/en/) (v16.11.0 or higher)
-- [npm](https://www.npmjs.com/) (should come with Node.js)
+- [Deno](https://deno.com/) (v2.0 or higher)
 
 You will need a Discord bot token, which you can get by creating a new application in the [Discord developer portal](https://discord.com/developers/applications) by following the steps outlined in the [Discord developer documentation](https://discord.com/developers/docs/getting-started).
 
@@ -38,8 +37,8 @@ Set the required environment variables (see section [Environment variables](#env
 Then run the following commands to install the dependencies and start the bot (in development mode):
 
 ```sh
-npm i
-npm run dev
+deno install
+deno task dev
 ```
 
 ## Environment variables
@@ -133,12 +132,12 @@ Command cooldowns can be set using the `cooldown` field in the command's [option
 ```ts
 export default command(
   // This command has a cooldown of 30 seconds, and works on a per-user basis
-  { meta, cooldown: 30 /* ... */ }
+  { meta, cooldown: 30 /* ... */ },
 );
 
 export default command(
   // This command has a cooldown of 60 seconds, and works on a guild-wide basis
-  { meta, cooldown: { seconds: 60, scope: 'guild' } /* ... */ }
+  { meta, cooldown: { seconds: 60, scope: 'guild' } /* ... */ },
 );
 ```
 
@@ -165,7 +164,7 @@ const meta = new SlashCommandBuilder()
       .setName('example-option')
       .setDescription('Example option.')
       .setRequired(true)
-      .setAutocomplete(true)
+      .setAutocomplete(true),
   );
 
 export default command({
@@ -183,10 +182,10 @@ export default command({
       'Popular Topics: Embed preview',
     ];
     const filtered = choices.filter((choice) =>
-      choice.toLowerCase().startsWith(focusedValue.toLowerCase())
+      choice.toLowerCase().startsWith(focusedValue.toLowerCase()),
     );
     await interaction.respond(
-      filtered.map((choice) => ({ name: choice, value: choice }))
+      filtered.map((choice) => ({ name: choice, value: choice })),
     );
   },
 });
@@ -210,7 +209,7 @@ import { event } from '../utils';
 
 export default event('ready', ({ logger }, client) => {
   logger.system(
-    `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!`
+    `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!`,
   );
 });
 ```
@@ -350,7 +349,7 @@ admin.initializeApp({
 export const db = admin.database();
 ```
 
-Don't forget to add the `FIREBASE_SDK` and `DB_URL` environment variables to your `.env` and `env.ts` files if you use the above snippet. You'll also have to install the `firebase-admin` package using `npm i firebase-admin`.
+Don't forget to add the `FIREBASE_SDK` and `DB_URL` environment variables to your `.env` and `env.ts` files if you use the above snippet. You'll also have to install the `firebase-admin` package using `deno add firebase-admin`.
 
 ## Server
 
@@ -393,13 +392,25 @@ src
 
 ## Code style
 
-This template uses the [Prettier](https://prettier.io/) code formatter to automatically format the code.
-A command, `npm run format`, is provided to run Prettier on all files in the `src` folder and immediately fix any issues.
-You can also use the Prettier extension for your editor of choice to automatically format the code on save.
-
-A [`.prettierrc.json`](./.prettierrc.json) config file is provided to configure Prettier.
+This template uses the Deno built-in code formatter to automatically format the code.
+A command, `deno task fmt`, is provided to run the Deno formatter on all files in the `src` folder and immediately fix any issues.
+You can also use the Deno extension, with some [VS Code settings](https://stackoverflow.com/questions/66207931/how-to-format-on-save-with-the-deno-vscode-extension) to automatically format the code on save.
+
+If you prefer to use [Prettier](https://prettier.io/), you may include a `.prettierrc.json` file in the root of the project.
+The file will be ignored by git.
+To achieve the same formatting as the current settings in [deno.json](./deno.json), you can use the following configuration:
+
+```json
+{
+  "endOfLine": "auto",
+  "semi": true,
+  "singleQuote": true,
+  "tabWidth": 2,
+  "trailingComma": "all"
+}
+```
 
-The project also uses [ESLint](https://eslint.org/) to lint the code, a config for which is included in the [`.eslintrc.json`](./.eslintrc.json) file.
+The linter used is also the Deno built-in linter, which can be run using the `deno task lint` command (which is really just `deno lint --fix`).
 
 ## Contributing
 

From 53d79f86c7327e4265719126dde3c4b816fd7011 Mon Sep 17 00:00:00 2001
From: Thijn <thijnkroon@gmail.com>
Date: Sat, 9 Nov 2024 10:03:56 +0100
Subject: [PATCH 5/6] chore: remove json extension from .prettierrc

---
 .gitignore | 2 +-
 README.md  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index ef27776..7e600bd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
 .env
-.prettierrc.json
+.prettierrc
 
 /.vs/
 /.vscode/
diff --git a/README.md b/README.md
index 457ed1b..4bec51b 100644
--- a/README.md
+++ b/README.md
@@ -396,7 +396,7 @@ This template uses the Deno built-in code formatter to automatically format the
 A command, `deno task fmt`, is provided to run the Deno formatter on all files in the `src` folder and immediately fix any issues.
 You can also use the Deno extension, with some [VS Code settings](https://stackoverflow.com/questions/66207931/how-to-format-on-save-with-the-deno-vscode-extension) to automatically format the code on save.
 
-If you prefer to use [Prettier](https://prettier.io/), you may include a `.prettierrc.json` file in the root of the project.
+If you prefer to use [Prettier](https://prettier.io/), you may include a `.prettierrc` file in the root of the project.
 The file will be ignored by git.
 To achieve the same formatting as the current settings in [deno.json](./deno.json), you can use the following configuration:
 

From 71f2745ba87b2e53f3a46a9a7a68836a35045131 Mon Sep 17 00:00:00 2001
From: Thijn <thijnkroon@gmail.com>
Date: Sat, 9 Nov 2024 10:14:03 +0100
Subject: [PATCH 6/6] chore: format code

---
 src/events/interactionCreate/commands.ts | 11 +++++------
 src/utils/help.ts                        |  8 ++++----
 src/utils/pagination.ts                  |  4 ++--
 src/utils/paginators/help.ts             | 12 ++++++------
 src/utils/paginators/index.ts            |  3 ++-
 5 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/src/events/interactionCreate/commands.ts b/src/events/interactionCreate/commands.ts
index 41d63af..30bbd85 100644
--- a/src/events/interactionCreate/commands.ts
+++ b/src/events/interactionCreate/commands.ts
@@ -78,12 +78,11 @@ const checkCooldown = (
   if (!interaction.guildId) return null;
 
   const now = Date.now();
-  const timestamps =
-    cooldowns.get(interaction.commandName) ?? new Map<string, number>();
-  const timestamp =
-    timestamps.get(
-      scope === 'user' ? interaction.user.id : interaction.guildId,
-    ) ?? 0;
+  const timestamps = cooldowns.get(interaction.commandName) ??
+    new Map<string, number>();
+  const timestamp = timestamps.get(
+    scope === 'user' ? interaction.user.id : interaction.guildId,
+  ) ?? 0;
   const cooldownEnd = timestamp + seconds * 1000;
 
   if (now < cooldownEnd && !isAdmin) {
diff --git a/src/utils/help.ts b/src/utils/help.ts
index a6baff9..a3bd664 100644
--- a/src/utils/help.ts
+++ b/src/utils/help.ts
@@ -21,7 +21,7 @@ const filterCategories = (
   isAdmin = false,
 ) =>
   categories?.filter((c) =>
-    c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin),
+    c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin)
   );
 
 /** Cached filtered command categories */
@@ -40,11 +40,12 @@ const getCategories = (
   scope: 'private' | 'public',
   access: 'admin' | 'member',
 ) => {
-  if (!cats[scope][access])
+  if (!cats[scope][access]) {
     cats[scope][access] = filterCategories(
       scope === 'private' ? 'all' : 'public',
       access === 'admin',
     );
+  }
   return cats[scope][access];
 };
 
@@ -52,8 +53,7 @@ const getCategories = (
 export const helpSelectComponent = (
   interaction: BaseInteraction,
 ): ActionRowBuilder<StringSelectMenuBuilder> | null => {
-  const isAdmin =
-    interaction.memberPermissions &&
+  const isAdmin = interaction.memberPermissions &&
     interaction.memberPermissions.has(PermissionFlagsBits.Administrator);
 
   // Categories specific to this guild (test guild or not)
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index 119a7bf..9f946b3 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -231,8 +231,8 @@ export class Paginator {
       backButton,
       nextButton,
     );
-    const selectMenu =
-      new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
+    const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>()
+      .addComponents(
         pageSelector,
       );
 
diff --git a/src/utils/paginators/help.ts b/src/utils/paginators/help.ts
index dc427d8..0edc22d 100644
--- a/src/utils/paginators/help.ts
+++ b/src/utils/paginators/help.ts
@@ -40,7 +40,7 @@ const extractSubcommandsRecursive = (
     option.options?.forEach((sub) =>
       result.push(
         ...extractSubcommandsRecursive(sub, `${name} ${option.name}`, cmdOpts),
-      ),
+      )
     );
   }
   return result;
@@ -57,7 +57,7 @@ const getCommands = (command: Command): PaginationData => {
       option.toJSON(),
       command.meta.name,
       command.options,
-    ),
+    )
   );
 
   // If no subcommands are found, this command is a standalone command
@@ -112,8 +112,7 @@ const helpPaginators = () =>
     return new Paginator(category.name, {
       embedData: {
         title: `${emoji}${category.name} Commands`,
-        description:
-          category.description ??
+        description: category.description ??
           `Browse through ${category.commands.public.length} command${
             category.commands.public.length > 1 ? 's' : ''
           } in ${emoji}${category.name}`,
@@ -126,8 +125,9 @@ const helpPaginators = () =>
       },
       pageLength: 10,
       getData: ({ interaction }) => {
-        const guildCmds =
-          interaction.guildId === ENV.TEST_GUILD ? cmds.private : cmds.public;
+        const guildCmds = interaction.guildId === ENV.TEST_GUILD
+          ? cmds.private
+          : cmds.public;
         if (
           interaction.memberPermissions &&
           interaction.memberPermissions.has(PermissionFlagsBits.Administrator)
diff --git a/src/utils/paginators/index.ts b/src/utils/paginators/index.ts
index 12bc10a..2a57257 100644
--- a/src/utils/paginators/index.ts
+++ b/src/utils/paginators/index.ts
@@ -14,8 +14,9 @@ const paginatorMap = new Map<string, Paginator>(
 );
 
 export function initPaginators() {
-  for (const paginator of helpPaginators())
+  for (const paginator of helpPaginators()) {
     paginatorMap.set(paginator.name, paginator);
+  }
 }
 
 /**