diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c34201d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +node_modules +dist +*.zip +_build +packets.mjs +*.log +test-context/ +servers/ +burgerpanel.sqlite3* +.git +burgerpanel-db-backup* +connector.burgerpanelsock diff --git a/.gitignore b/.gitignore index 4a49ed9..d72fb7c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ Web/dist Share/BuildInfo.ts Server/data.json testing/ +/db/ +/servers/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..05a7c50 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM node:23-alpine +RUN corepack enable +COPY . /panelbuild/ +RUN rm -rf /panelbuild/Server/node_modules /panelbuild/Web/node_modules +WORKDIR /panelbuild/Server +ENV BURGERPANEL_DOCKER=1 +RUN pnpm i +RUN pnpm buildRelease +FROM node:23-alpine +RUN apk update +RUN apk add openjdk21 +WORKDIR /panel +COPY --from=0 /panelbuild/Server/node_modules/better-sqlite3/build/Release/better_sqlite3.node /panel/better_sqlite3.node +COPY --from=0 /panelbuild/Server/_build/ /panel +CMD [ "node", "burgerpanel.mjs" ] \ No newline at end of file diff --git a/Integrator/src/main/java/io/github/theblueburger/burgerpanelintegrator/BurgerPanelIntegrator.java b/Integrator/src/main/java/io/github/theblueburger/burgerpanelintegrator/BurgerPanelIntegrator.java index 08aedf1..77d97ba 100644 --- a/Integrator/src/main/java/io/github/theblueburger/burgerpanelintegrator/BurgerPanelIntegrator.java +++ b/Integrator/src/main/java/io/github/theblueburger/burgerpanelintegrator/BurgerPanelIntegrator.java @@ -1,6 +1,8 @@ package io.github.theblueburger.burgerpanelintegrator; import io.github.theblueburger.burgerpanelintegrator.packets.*; + +import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; @@ -120,6 +122,12 @@ public void run() { @Override public void onDisable() { try { + if(Bukkit.getServer().isStopping()) { + JSONObject stoppingJsonObject = new JSONObject(); + stoppingJsonObject.put("dataType", "request"); + stoppingJsonObject.put("type", "serverStopping"); + write(stoppingJsonObject); + } client.close(); } catch (IOException ignored) { diff --git a/Integrator/src/main/java/io/github/theblueburger/burgerpanelintegrator/packets/StatusPacket.java b/Integrator/src/main/java/io/github/theblueburger/burgerpanelintegrator/packets/StatusPacket.java index fe4e137..adc4d78 100644 --- a/Integrator/src/main/java/io/github/theblueburger/burgerpanelintegrator/packets/StatusPacket.java +++ b/Integrator/src/main/java/io/github/theblueburger/burgerpanelintegrator/packets/StatusPacket.java @@ -32,6 +32,7 @@ protected void execute(JSONObject data, String id) throws IOException { locationObj.put("z", location.getZ()); locationObj.put("world", location.getWorld().getName()); playerObject.put("location", locationObj); + playerObject.put("gamemode", player.getGameMode().getValue()); playerArray.add(playerObject); } responseObj.put("players", playerArray); diff --git a/Server/.gitignore b/Server/.gitignore index 98d2ae4..cc97537 100644 --- a/Server/.gitignore +++ b/Server/.gitignore @@ -7,3 +7,5 @@ packets.mjs *.log test-context/ servers/ +burgerpanel.sqlite3* +burgerpanel-db-backup-* \ No newline at end of file diff --git a/Server/Gulpfile.mjs b/Server/Gulpfile.mjs index 256a4b2..bb9a67a 100644 --- a/Server/Gulpfile.mjs +++ b/Server/Gulpfile.mjs @@ -6,6 +6,8 @@ import esbuild from "esbuild"; import packageJSON from "./package.json" with {type: "json"} import path from "path"; +const isDocker = process.env.BURGERPANEL_DOCKER == "1"; + async function installWebIfForgotten() { if(!existsSync("../Web/node_modules")) { console.log("Installing web packages..."); @@ -55,10 +57,11 @@ async function runESBuild() { format: "esm", target: "es2022", banner: { - js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);" // read comments in /src/clients.ts to see explanation for this + js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);import * as url from 'url';const __filename = url.fileURLToPath(import.meta.url);" // read comments in /src/clients.ts to see explanation for this }, define: { - "process.env.NODE_ENV": "\"production\"" + "process.env.NODE_ENV": "\"production\"", + "process.env.IS_DOCKER": isDocker ? "1" : "0" }, outfile: "_build/burgerpanel.mjs", }); @@ -105,7 +108,7 @@ async function copyFiles() { fs.copyFileSync("../LICENSE", "_build/LICENSE.txt"); fs.copyFileSync("../README.md", "_build/README.txt"); if(!process.env.SKIP_WEB) fs.cpSync("../Web/dist/", "_build/Web", {recursive: true}); - fs.writeFileSync("_build/mongodb_url.txt", "json:data.json"); + fs.writeFileSync("_build/package.json", "{}"); } async function serverSeries() { diff --git a/Server/buildTools/buildInfo.mjs b/Server/buildTools/buildInfo.mjs index a4e8d79..905bc74 100644 --- a/Server/buildTools/buildInfo.mjs +++ b/Server/buildTools/buildInfo.mjs @@ -1,19 +1,21 @@ import fs from "node:fs"; import os from "node:os"; import { execSync } from "node:child_process"; -let userInfo = os.userInfo(); -let gitHash; -let branch; -try { - gitHash = execSync("git rev-parse HEAD").toString().trim(); - branch = execSync("git rev-parse --abbrev-ref HEAD").toString().trim(); -} catch {} import packageJSON from "../package.json" with {type: "json"} -fs.writeFileSync("../Share/BuildInfo.ts", "export let buildInfo = " + JSON.stringify({ - date: Date.now(), - version: packageJSON.version, - compiledBy: userInfo.username, - builtOn: process.platform, - gitHash, - branch -})); \ No newline at end of file +if(process.env.BURGERPANEL_DOCKER != "1") { + let userInfo = os.userInfo(); + let gitHash; + let branch; + try { + gitHash = execSync("git rev-parse HEAD").toString().trim(); + branch = execSync("git rev-parse --abbrev-ref HEAD").toString().trim(); + } catch {} + fs.writeFileSync("../Share/BuildInfo.ts", "export let buildInfo = " + JSON.stringify({ + date: Date.now(), + version: packageJSON.version, + compiledBy: userInfo.username, + builtOn: process.platform, + gitHash, + branch + })); +} \ No newline at end of file diff --git a/Server/docker-compose.yml b/Server/docker-compose.yml deleted file mode 100644 index b81f4d6..0000000 --- a/Server/docker-compose.yml +++ /dev/null @@ -1,18 +0,0 @@ -services: - db: - image: docker.io/mongo - environment: - - MONGO_INITDB_ROOT_USERNAME=root - - MONGO_INITDB_ROOT_PASSWORD=uhNUohnUihnuiOHBNUJhnuIJBNujiB - - MONGO_INITDB_DATABASE=burgerpanel - volumes: - - data:/data/db - - ./init-mongo-user.js:/docker-entrypoint-initdb.d/mongo-init.js:ro - ports: - - "27017:27017" - expose: - - 27017 - -volumes: - data: - \ No newline at end of file diff --git a/Server/init-mongo-user.js b/Server/init-mongo-user.js deleted file mode 100644 index 84df0c9..0000000 --- a/Server/init-mongo-user.js +++ /dev/null @@ -1,10 +0,0 @@ -db.createUser({ - user: "burgerpanel", - pwd: "burgerpanel", - roles: [ - { - role: "readWrite", - db: "burgerpanel" - } - ] -}); \ No newline at end of file diff --git a/Server/mongodb_url.txt b/Server/mongodb_url.txt deleted file mode 100644 index 2eff48f..0000000 --- a/Server/mongodb_url.txt +++ /dev/null @@ -1 +0,0 @@ -json:data.json \ No newline at end of file diff --git a/Server/package.json b/Server/package.json index 60d7b03..338b972 100644 --- a/Server/package.json +++ b/Server/package.json @@ -22,19 +22,19 @@ "devDependencies": { "@types/express": "^4.17.21", "@types/mime-types": "^2.1.4", - "@types/ws": "^8.5.12", - "@vitest/ui": "^2.1.2", + "@types/ws": "^8.5.13", + "@vitest/ui": "^2.1.8", "esbuild": "^0.24.0", "gulp": "^5.0.0", - "typescript": "^5.6.2", - "vitest": "^2.1.2" + "typescript": "^5.7.2", + "vitest": "^2.1.8" }, "dependencies": { + "@types/better-sqlite3": "^7.6.12", + "better-sqlite3": "^11.7.0", "blueutilities": "^1.2.2", "chalk": "^5.3.0", - "express": "^4.21.0", - "mime-types": "^2.1.35", - "mongoose": "^8.7.0", + "express": "^4.21.2", "ws": "^8.18.0" }, "packageManager": "pnpm@9.1.0+sha256.22e36fba7f4880ecf749a5ca128b8435da085ecd49575e7fb9e64d6bf4fad394" diff --git a/Server/pnpm-lock.yaml b/Server/pnpm-lock.yaml index a43033a..05927a0 100644 --- a/Server/pnpm-lock.yaml +++ b/Server/pnpm-lock.yaml @@ -8,6 +8,12 @@ importers: .: dependencies: + '@types/better-sqlite3': + specifier: ^7.6.12 + version: 7.6.12 + better-sqlite3: + specifier: ^11.7.0 + version: 11.7.0 blueutilities: specifier: ^1.2.2 version: 1.2.2 @@ -15,14 +21,8 @@ importers: specifier: ^5.3.0 version: 5.3.0 express: - specifier: ^4.21.0 - version: 4.21.0 - mime-types: - specifier: ^2.1.35 - version: 2.1.35 - mongoose: - specifier: ^8.7.0 - version: 8.7.0 + specifier: ^4.21.2 + version: 4.21.2 ws: specifier: ^8.18.0 version: 8.18.0 @@ -34,11 +34,11 @@ importers: specifier: ^2.1.4 version: 2.1.4 '@types/ws': - specifier: ^8.5.12 - version: 8.5.12 + specifier: ^8.5.13 + version: 8.5.13 '@vitest/ui': - specifier: ^2.1.2 - version: 2.1.2(vitest@2.1.2) + specifier: ^2.1.8 + version: 2.1.8(vitest@2.1.8) esbuild: specifier: ^0.24.0 version: 0.24.0 @@ -46,11 +46,11 @@ importers: specifier: ^5.0.0 version: 5.0.0 typescript: - specifier: ^5.6.2 - version: 5.6.2 + specifier: ^5.7.2 + version: 5.7.2 vitest: - specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.4)(@vitest/ui@2.1.2) + specifier: ^2.1.8 + version: 2.1.8(@types/node@22.10.1)(@vitest/ui@2.1.8) packages: @@ -347,92 +347,107 @@ packages: '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - '@mongodb-js/saslprep@1.1.9': - resolution: {integrity: sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==} - '@polka/url@1.0.0-next.28': resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} - '@rollup/rollup-android-arm-eabi@4.24.0': - resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} + '@rollup/rollup-android-arm-eabi@4.28.1': + resolution: {integrity: sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.24.0': - resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} + '@rollup/rollup-android-arm64@4.28.1': + resolution: {integrity: sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.24.0': - resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} + '@rollup/rollup-darwin-arm64@4.28.1': + resolution: {integrity: sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.24.0': - resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} + '@rollup/rollup-darwin-x64@4.28.1': + resolution: {integrity: sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.24.0': - resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} + '@rollup/rollup-freebsd-arm64@4.28.1': + resolution: {integrity: sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.28.1': + resolution: {integrity: sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.28.1': + resolution: {integrity: sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.24.0': - resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} + '@rollup/rollup-linux-arm-musleabihf@4.28.1': + resolution: {integrity: sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.24.0': - resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} + '@rollup/rollup-linux-arm64-gnu@4.28.1': + resolution: {integrity: sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.24.0': - resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} + '@rollup/rollup-linux-arm64-musl@4.28.1': + resolution: {integrity: sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': - resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} + '@rollup/rollup-linux-loongarch64-gnu@4.28.1': + resolution: {integrity: sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.28.1': + resolution: {integrity: sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.24.0': - resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} + '@rollup/rollup-linux-riscv64-gnu@4.28.1': + resolution: {integrity: sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.24.0': - resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} + '@rollup/rollup-linux-s390x-gnu@4.28.1': + resolution: {integrity: sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.24.0': - resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} + '@rollup/rollup-linux-x64-gnu@4.28.1': + resolution: {integrity: sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.24.0': - resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} + '@rollup/rollup-linux-x64-musl@4.28.1': + resolution: {integrity: sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.24.0': - resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} + '@rollup/rollup-win32-arm64-msvc@4.28.1': + resolution: {integrity: sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.24.0': - resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} + '@rollup/rollup-win32-ia32-msvc@4.28.1': + resolution: {integrity: sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.24.0': - resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} + '@rollup/rollup-win32-x64-msvc@4.28.1': + resolution: {integrity: sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==} cpu: [x64] os: [win32] + '@types/better-sqlite3@7.6.12': + resolution: {integrity: sha512-fnQmj8lELIj7BSrZQAdBMHEHX8OZLYIHXqAKT1O7tDfLxaINzf00PMjw22r3N/xXh0w/sGHlO6SVaCQ2mj78lg==} + '@types/body-parser@1.19.5': resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} @@ -442,8 +457,8 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/express-serve-static-core@4.19.3': - resolution: {integrity: sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg==} + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -457,14 +472,14 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/node@20.14.2': - resolution: {integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==} + '@types/node@22.10.1': + resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} '@types/node@22.7.4': resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==} - '@types/qs@6.9.15': - resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} + '@types/qs@6.9.17': + resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==} '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} @@ -475,23 +490,16 @@ packages: '@types/serve-static@1.15.7': resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - '@types/webidl-conversions@7.0.3': - resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} - - '@types/whatwg-url@11.0.5': - resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==} + '@types/ws@8.5.13': + resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==} - '@types/ws@8.5.12': - resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} + '@vitest/expect@2.1.8': + resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==} - '@vitest/expect@2.1.2': - resolution: {integrity: sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg==} - - '@vitest/mocker@2.1.2': - resolution: {integrity: sha512-ExElkCGMS13JAJy+812fw1aCv2QO/LBK6CyO4WOPAzLTmve50gydOlWhgdBJPx2ztbADUq3JVI0C5U+bShaeEA==} + '@vitest/mocker@2.1.8': + resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==} peerDependencies: - '@vitest/spy': 2.1.2 - msw: ^2.3.5 + msw: ^2.4.9 vite: ^5.0.0 peerDependenciesMeta: msw: @@ -499,25 +507,25 @@ packages: vite: optional: true - '@vitest/pretty-format@2.1.2': - resolution: {integrity: sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA==} + '@vitest/pretty-format@2.1.8': + resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==} - '@vitest/runner@2.1.2': - resolution: {integrity: sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw==} + '@vitest/runner@2.1.8': + resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==} - '@vitest/snapshot@2.1.2': - resolution: {integrity: sha512-xtAeNsZ++aRIYIUsek7VHzry/9AcxeULlegBvsdLncLmNCR6tR8SRjn8BbDP4naxtccvzTqZ+L1ltZlRCfBZFA==} + '@vitest/snapshot@2.1.8': + resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==} - '@vitest/spy@2.1.2': - resolution: {integrity: sha512-GSUi5zoy+abNRJwmFhBDC0yRuVUn8WMlQscvnbbXdKLXX9dE59YbfwXxuJ/mth6eeqIzofU8BB5XDo/Ns/qK2A==} + '@vitest/spy@2.1.8': + resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==} - '@vitest/ui@2.1.2': - resolution: {integrity: sha512-92gcNzkDnmxOxyHzQrQYRsoV9Q0Aay0r4QMLnV+B+lbqlUWa8nDg9ivyLV5mMVTtGirHsYUGGh/zbIA55gBZqA==} + '@vitest/ui@2.1.8': + resolution: {integrity: sha512-5zPJ1fs0ixSVSs5+5V2XJjXLmNzjugHRyV11RqxYVR+oMcogZ9qTuSfKW+OcTV0JeFNznI83BNylzH6SSNJ1+w==} peerDependencies: - vitest: 2.1.2 + vitest: 2.1.8 - '@vitest/utils@2.1.2': - resolution: {integrity: sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ==} + '@vitest/utils@2.1.8': + resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==} accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} @@ -571,10 +579,19 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + better-sqlite3@11.7.0: + resolution: {integrity: sha512-mXpa5jnIKKHeoGzBrUJrc65cXFKcILGZpU3FXR0pradUEm9MA7UZz02qfEejaMcm9iXrSOCenwwYMJ/tZ1y5Ig==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + bl@5.1.0: resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} @@ -589,9 +606,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - bson@6.8.0: - resolution: {integrity: sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==} - engines: {node: '>=16.20.1'} + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} @@ -604,12 +620,16 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + call-bind-apply-helpers@1.0.1: + resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} engines: {node: '>= 0.4'} - chai@5.1.1: - resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + chai@5.1.2: + resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} engines: {node: '>=12'} chalk@4.1.2: @@ -628,6 +648,9 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} @@ -659,8 +682,8 @@ packages: cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} copy-props@4.0.0: @@ -675,8 +698,8 @@ packages: supports-color: optional: true - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -684,10 +707,18 @@ packages: supports-color: optional: true + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -704,6 +735,14 @@ packages: resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} engines: {node: '>=0.10.0'} + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + dunder-proto@1.0.0: + resolution: {integrity: sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==} + engines: {node: '>= 0.4'} + each-props@3.0.0: resolution: {integrity: sha512-IYf1hpuWrdzse/s/YJOrFmU15lyhSzxelNVAHTEG3DtP4QsLTWZUzcUL3HMXmKQxXpa4EIrBPpwRgj0aehdvAw==} engines: {node: '>= 10.13.0'} @@ -725,14 +764,17 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -757,12 +799,20 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + expand-tilde@2.0.2: resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} engines: {node: '>=0.10.0'} - express@4.21.0: - resolution: {integrity: sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==} + expect-type@1.1.0: + resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} + engines: {node: '>=12.0.0'} + + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} extend@3.0.2: @@ -781,8 +831,8 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fdir@6.4.0: - resolution: {integrity: sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==} + fdir@6.4.2: + resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -792,6 +842,9 @@ packages: fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -812,8 +865,8 @@ packages: resolution: {integrity: sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==} engines: {node: '>= 10.13.0'} - flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + flatted@3.3.2: + resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} for-in@1.0.2: resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} @@ -831,6 +884,9 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-mkdirp-stream@2.0.1: resolution: {integrity: sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==} engines: {node: '>=10.13.0'} @@ -847,13 +903,13 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + get-intrinsic@1.2.5: + resolution: {integrity: sha512-Y4+pKa7XeRUPWFNvOOYHkRYrfzW07oraURSvjDmRVOJ748OrVmeXtpE4+GCEHncjCjkTxPNRt8kEbxDhsn6VTg==} engines: {node: '>= 0.4'} + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -882,8 +938,9 @@ packages: resolution: {integrity: sha512-eWv1ds/zAlz+M1ioHsyKJomfY7jbDDPpwSkv14KQj89bycx1nvK5/2Cj/T9g7kzJcX5Bc7Yv22FjfBZS/jl94A==} engines: {node: '>= 10.13.0'} - gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -909,12 +966,8 @@ packages: has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - - has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} hasown@2.0.2: @@ -1012,10 +1065,6 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} - kareem@2.6.3: - resolution: {integrity: sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==} - engines: {node: '>=12.0.0'} - last-run@2.0.0: resolution: {integrity: sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ==} engines: {node: '>= 10.13.0'} @@ -1028,11 +1077,11 @@ packages: resolution: {integrity: sha512-a5BQjbCHnB+cy+gsro8lXJ4kZluzOijzJ1UVVfyJYZC+IP2pLv1h4+aysQeKuTmyO8NAqfyQAk4HWaP/HjcKTg==} engines: {node: '>=10.13.0'} - loupe@3.1.1: - resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} + loupe@3.1.2: + resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} - magic-string@0.30.11: - resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + magic-string@0.30.14: + resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==} map-cache@0.2.2: resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} @@ -1042,9 +1091,6 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - memory-pager@1.5.0: - resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} - merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} @@ -1069,47 +1115,15 @@ packages: engines: {node: '>=4'} hasBin: true - mongodb-connection-string-url@3.0.1: - resolution: {integrity: sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==} - - mongodb@6.9.0: - resolution: {integrity: sha512-UMopBVx1LmEUbW/QE0Hw18u583PEDVQmUmVzzBRH0o/xtE9DBRA5ZYLOjpLIa03i8FXjzvQECJcqoMvCXftTUA==} - engines: {node: '>=16.20.1'} - peerDependencies: - '@aws-sdk/credential-providers': ^3.188.0 - '@mongodb-js/zstd': ^1.1.0 - gcp-metadata: ^5.2.0 - kerberos: ^2.0.1 - mongodb-client-encryption: '>=6.0.0 <7' - snappy: ^7.2.2 - socks: ^2.7.1 - peerDependenciesMeta: - '@aws-sdk/credential-providers': - optional: true - '@mongodb-js/zstd': - optional: true - gcp-metadata: - optional: true - kerberos: - optional: true - mongodb-client-encryption: - optional: true - snappy: - optional: true - socks: - optional: true + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} - mongoose@8.7.0: - resolution: {integrity: sha512-rUCSF1mMYQXjXYdqEQLLlMD3xbcj2j1/hRn+9VnVj7ipzru/UoUZxlj/hWmteKMAh4EFnDZ+BIrmma9l/0Hi1g==} - engines: {node: '>=16.20.1'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - mpath@0.9.0: - resolution: {integrity: sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==} - engines: {node: '>=4.0.0'} - - mquery@5.0.0: - resolution: {integrity: sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==} - engines: {node: '>=14.0.0'} + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} mrmime@2.0.0: resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} @@ -1125,15 +1139,22 @@ packages: resolution: {integrity: sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ==} engines: {node: '>= 10.13.0'} - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + napi-build-utils@1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} + node-abi@3.71.0: + resolution: {integrity: sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==} + engines: {node: '>=10'} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -1142,8 +1163,8 @@ packages: resolution: {integrity: sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==} engines: {node: '>= 10.13.0'} - object-inspect@1.13.2: - resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + object-inspect@1.13.3: + resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} engines: {node: '>= 0.4'} object.defaults@1.1.0: @@ -1184,8 +1205,8 @@ packages: resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} engines: {node: '>=0.10.0'} - path-to-regexp@0.1.10: - resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -1194,8 +1215,8 @@ packages: resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} engines: {node: '>= 14.16'} - picocolors@1.1.0: - resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -1205,17 +1226,21 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} - postcss@8.4.47: - resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} + prebuild-install@7.1.2: + resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} + engines: {node: '>=10'} + hasBin: true + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} qs@6.13.0: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} @@ -1232,6 +1257,10 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -1275,8 +1304,8 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.24.0: - resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} + rollup@4.28.1: + resolution: {integrity: sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -1294,6 +1323,11 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} @@ -1313,15 +1347,18 @@ packages: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} - sift@17.1.3: - resolution: {integrity: sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==} - siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - sirv@2.0.4: - resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} - engines: {node: '>= 10'} + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + + sirv@3.0.0: + resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==} + engines: {node: '>=18'} source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} @@ -1331,9 +1368,6 @@ packages: resolution: {integrity: sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg==} engines: {node: '>= 10.13.0'} - sparse-bitfield@3.0.3: - resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} - stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -1341,8 +1375,8 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - std-env@3.7.0: - resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + std-env@3.8.0: + resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} stream-composer@1.0.2: resolution: {integrity: sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==} @@ -1364,6 +1398,10 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1375,6 +1413,13 @@ packages: sver@1.8.4: resolution: {integrity: sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA==} + tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + teex@1.0.1: resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} @@ -1384,15 +1429,15 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@0.3.0: - resolution: {integrity: sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==} + tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} - tinyglobby@0.2.9: - resolution: {integrity: sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==} + tinyglobby@0.2.10: + resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} engines: {node: '>=12.0.0'} - tinypool@1.0.1: - resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==} + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} engines: {node: ^18.0.0 || >=20.0.0} tinyrainbow@1.2.0: @@ -1419,16 +1464,15 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} - tr46@4.1.1: - resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} - engines: {node: '>=14'} + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} - typescript@5.6.2: - resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} engines: {node: '>=14.17'} hasBin: true @@ -1444,12 +1488,12 @@ packages: resolution: {integrity: sha512-tO/bf30wBbTsJ7go80j0RzA2rcwX6o7XPBpeFcb+jzoeb4pfMM2zUeSDIkY1AWqeZabWxaQZ/h8N9t35QKDLPQ==} engines: {node: '>=10.13.0'} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -1489,13 +1533,13 @@ packages: resolution: {integrity: sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==} engines: {node: '>=10.13.0'} - vite-node@2.1.2: - resolution: {integrity: sha512-HPcGNN5g/7I2OtPjLqgOtCRu/qhVvBxTUD3qzitmL0SrG1cWFzxzhMDWussxSbrRYWqnKf8P2jiNhPMSN+ymsQ==} + vite-node@2.1.8: + resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.4.8: - resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} + vite@5.4.11: + resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -1525,15 +1569,15 @@ packages: terser: optional: true - vitest@2.1.2: - resolution: {integrity: sha512-veNjLizOMkRrJ6xxb+pvxN6/QAWg95mzcRjtmkepXdN87FNfxAss9RKe2far/G9cQpipfgP2taqg0KiWsquj8A==} + vitest@2.1.8: + resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.1.2 - '@vitest/ui': 2.1.2 + '@vitest/browser': 2.1.8 + '@vitest/ui': 2.1.8 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -1550,14 +1594,6 @@ packages: jsdom: optional: true - webidl-conversions@7.0.0: - resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} - engines: {node: '>=12'} - - whatwg-url@13.0.0: - resolution: {integrity: sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==} - engines: {node: '>=16'} - which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true @@ -1749,83 +1785,92 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.0': {} - '@mongodb-js/saslprep@1.1.9': - dependencies: - sparse-bitfield: 3.0.3 - '@polka/url@1.0.0-next.28': {} - '@rollup/rollup-android-arm-eabi@4.24.0': + '@rollup/rollup-android-arm-eabi@4.28.1': + optional: true + + '@rollup/rollup-android-arm64@4.28.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.28.1': + optional: true + + '@rollup/rollup-darwin-x64@4.28.1': optional: true - '@rollup/rollup-android-arm64@4.24.0': + '@rollup/rollup-freebsd-arm64@4.28.1': optional: true - '@rollup/rollup-darwin-arm64@4.24.0': + '@rollup/rollup-freebsd-x64@4.28.1': optional: true - '@rollup/rollup-darwin-x64@4.24.0': + '@rollup/rollup-linux-arm-gnueabihf@4.28.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + '@rollup/rollup-linux-arm-musleabihf@4.28.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.24.0': + '@rollup/rollup-linux-arm64-gnu@4.28.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.24.0': + '@rollup/rollup-linux-arm64-musl@4.28.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.24.0': + '@rollup/rollup-linux-loongarch64-gnu@4.28.1': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.28.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.24.0': + '@rollup/rollup-linux-riscv64-gnu@4.28.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.24.0': + '@rollup/rollup-linux-s390x-gnu@4.28.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.24.0': + '@rollup/rollup-linux-x64-gnu@4.28.1': optional: true - '@rollup/rollup-linux-x64-musl@4.24.0': + '@rollup/rollup-linux-x64-musl@4.28.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.24.0': + '@rollup/rollup-win32-arm64-msvc@4.28.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.24.0': + '@rollup/rollup-win32-ia32-msvc@4.28.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.24.0': + '@rollup/rollup-win32-x64-msvc@4.28.1': optional: true + '@types/better-sqlite3@7.6.12': + dependencies: + '@types/node': 22.7.4 + '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.14.2 + '@types/node': 22.10.1 '@types/connect@3.4.38': dependencies: - '@types/node': 20.14.2 + '@types/node': 22.10.1 '@types/estree@1.0.6': {} - '@types/express-serve-static-core@4.19.3': + '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 20.14.2 - '@types/qs': 6.9.15 + '@types/node': 22.10.1 + '@types/qs': 6.9.17 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.3 - '@types/qs': 6.9.15 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.9.17 '@types/serve-static': 1.15.7 '@types/http-errors@2.0.4': {} @@ -1834,88 +1879,82 @@ snapshots: '@types/mime@1.3.5': {} - '@types/node@20.14.2': + '@types/node@22.10.1': dependencies: - undici-types: 5.26.5 + undici-types: 6.20.0 '@types/node@22.7.4': dependencies: undici-types: 6.19.8 - '@types/qs@6.9.15': {} + '@types/qs@6.9.17': {} '@types/range-parser@1.2.7': {} '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.14.2 + '@types/node': 22.10.1 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.14.2 + '@types/node': 22.10.1 '@types/send': 0.17.4 - '@types/webidl-conversions@7.0.3': {} - - '@types/whatwg-url@11.0.5': - dependencies: - '@types/webidl-conversions': 7.0.3 - - '@types/ws@8.5.12': + '@types/ws@8.5.13': dependencies: - '@types/node': 22.7.4 + '@types/node': 22.10.1 - '@vitest/expect@2.1.2': + '@vitest/expect@2.1.8': dependencies: - '@vitest/spy': 2.1.2 - '@vitest/utils': 2.1.2 - chai: 5.1.1 + '@vitest/spy': 2.1.8 + '@vitest/utils': 2.1.8 + chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@22.7.4))': + '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.1))': dependencies: - '@vitest/spy': 2.1.2 + '@vitest/spy': 2.1.8 estree-walker: 3.0.3 - magic-string: 0.30.11 + magic-string: 0.30.14 optionalDependencies: - vite: 5.4.8(@types/node@22.7.4) + vite: 5.4.11(@types/node@22.10.1) - '@vitest/pretty-format@2.1.2': + '@vitest/pretty-format@2.1.8': dependencies: tinyrainbow: 1.2.0 - '@vitest/runner@2.1.2': + '@vitest/runner@2.1.8': dependencies: - '@vitest/utils': 2.1.2 + '@vitest/utils': 2.1.8 pathe: 1.1.2 - '@vitest/snapshot@2.1.2': + '@vitest/snapshot@2.1.8': dependencies: - '@vitest/pretty-format': 2.1.2 - magic-string: 0.30.11 + '@vitest/pretty-format': 2.1.8 + magic-string: 0.30.14 pathe: 1.1.2 - '@vitest/spy@2.1.2': + '@vitest/spy@2.1.8': dependencies: tinyspy: 3.0.2 - '@vitest/ui@2.1.2(vitest@2.1.2)': + '@vitest/ui@2.1.8(vitest@2.1.8)': dependencies: - '@vitest/utils': 2.1.2 + '@vitest/utils': 2.1.8 fflate: 0.8.2 - flatted: 3.3.1 + flatted: 3.3.2 pathe: 1.1.2 - sirv: 2.0.4 - tinyglobby: 0.2.9 + sirv: 3.0.0 + tinyglobby: 0.2.10 tinyrainbow: 1.2.0 - vitest: 2.1.2(@types/node@22.7.4)(@vitest/ui@2.1.2) + vitest: 2.1.8(@types/node@22.10.1)(@vitest/ui@2.1.8) - '@vitest/utils@2.1.2': + '@vitest/utils@2.1.8': dependencies: - '@vitest/pretty-format': 2.1.2 - loupe: 3.1.1 + '@vitest/pretty-format': 2.1.8 + loupe: 3.1.2 tinyrainbow: 1.2.0 accepts@1.3.8: @@ -1965,8 +2004,23 @@ snapshots: base64-js@1.5.1: {} + better-sqlite3@11.7.0: + dependencies: + bindings: 1.5.0 + prebuild-install: 7.1.2 + binary-extensions@2.3.0: {} + bindings@1.5.0: + dependencies: + file-uri-to-path: 1.0.0 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + bl@5.1.0: dependencies: buffer: 6.0.3 @@ -1996,7 +2050,10 @@ snapshots: dependencies: fill-range: 7.1.1 - bson@6.8.0: {} + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 buffer@6.0.3: dependencies: @@ -2007,20 +2064,24 @@ snapshots: cac@6.7.14: {} - call-bind@1.0.7: + call-bind-apply-helpers@1.0.1: dependencies: - es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-define-property: 1.0.1 + get-intrinsic: 1.2.5 set-function-length: 1.2.2 - chai@5.1.1: + chai@5.1.2: dependencies: assertion-error: 2.0.1 check-error: 2.1.1 deep-eql: 5.0.2 - loupe: 3.1.1 + loupe: 3.1.2 pathval: 2.0.0 chalk@4.1.2: @@ -2044,6 +2105,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chownr@1.1.4: {} + cliui@7.0.4: dependencies: string-width: 4.2.3 @@ -2070,7 +2133,7 @@ snapshots: cookie-signature@1.0.6: {} - cookie@0.6.0: {} + cookie@0.7.1: {} copy-props@4.0.0: dependencies: @@ -2081,17 +2144,23 @@ snapshots: dependencies: ms: 2.0.0 - debug@4.3.7: + debug@4.4.0: dependencies: ms: 2.1.3 + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + deep-eql@5.0.2: {} + deep-extend@0.6.0: {} + define-data-property@1.1.4: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 es-errors: 1.3.0 - gopd: 1.0.1 + gopd: 1.2.0 depd@2.0.0: {} @@ -2099,6 +2168,14 @@ snapshots: detect-file@1.0.0: {} + detect-libc@2.0.3: {} + + dunder-proto@1.0.0: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + each-props@3.0.0: dependencies: is-plain-object: 5.0.0 @@ -2116,12 +2193,12 @@ snapshots: dependencies: once: 1.4.0 - es-define-property@1.0.0: - dependencies: - get-intrinsic: 1.2.4 + es-define-property@1.0.1: {} es-errors@1.3.0: {} + es-module-lexer@1.5.4: {} + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -2185,18 +2262,22 @@ snapshots: etag@1.8.1: {} + expand-template@2.0.3: {} + expand-tilde@2.0.2: dependencies: homedir-polyfill: 1.0.3 - express@4.21.0: + expect-type@1.1.0: {} + + express@4.21.2: dependencies: accepts: 1.3.8 array-flatten: 1.1.1 body-parser: 1.20.3 content-disposition: 0.5.4 content-type: 1.0.5 - cookie: 0.6.0 + cookie: 0.7.1 cookie-signature: 1.0.6 debug: 2.6.9 depd: 2.0.0 @@ -2210,7 +2291,7 @@ snapshots: methods: 1.1.2 on-finished: 2.4.1 parseurl: 1.3.3 - path-to-regexp: 0.1.10 + path-to-regexp: 0.1.12 proxy-addr: 2.0.7 qs: 6.13.0 range-parser: 1.2.1 @@ -2239,12 +2320,14 @@ snapshots: dependencies: reusify: 1.0.4 - fdir@6.4.0(picomatch@4.0.2): + fdir@6.4.2(picomatch@4.0.2): optionalDependencies: picomatch: 4.0.2 fflate@0.8.2: {} + file-uri-to-path@1.0.0: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -2278,7 +2361,7 @@ snapshots: flagged-respawn@2.0.0: {} - flatted@3.3.1: {} + flatted@3.3.2: {} for-in@1.0.2: {} @@ -2290,6 +2373,8 @@ snapshots: fresh@0.5.2: {} + fs-constants@1.0.0: {} + fs-mkdirp-stream@2.0.1: dependencies: graceful-fs: 4.2.11 @@ -2302,16 +2387,19 @@ snapshots: get-caller-file@2.0.5: {} - get-func-name@2.0.2: {} - - get-intrinsic@1.2.4: + get-intrinsic@1.2.5: dependencies: + call-bind-apply-helpers: 1.0.1 + dunder-proto: 1.0.0 + es-define-property: 1.0.1 es-errors: 1.3.0 function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 + gopd: 1.2.0 + has-symbols: 1.1.0 hasown: 2.0.2 + github-from-package@0.0.0: {} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2354,9 +2442,7 @@ snapshots: dependencies: sparkles: 2.1.0 - gopd@1.0.1: - dependencies: - get-intrinsic: 1.2.4 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -2390,11 +2476,9 @@ snapshots: has-property-descriptors@1.0.2: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 - has-proto@1.0.3: {} - - has-symbols@1.0.3: {} + has-symbols@1.1.0: {} hasown@2.0.2: dependencies: @@ -2473,8 +2557,6 @@ snapshots: isobject@3.0.1: {} - kareem@2.6.3: {} - last-run@2.0.0: {} lead@4.0.0: {} @@ -2489,11 +2571,9 @@ snapshots: rechoir: 0.8.0 resolve: 1.22.8 - loupe@3.1.1: - dependencies: - get-func-name: 2.0.2 + loupe@3.1.2: {} - magic-string@0.30.11: + magic-string@0.30.14: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -2501,8 +2581,6 @@ snapshots: media-typer@0.3.0: {} - memory-pager@1.5.0: {} - merge-descriptors@1.0.3: {} methods@1.1.2: {} @@ -2520,43 +2598,11 @@ snapshots: mime@1.6.0: {} - mongodb-connection-string-url@3.0.1: - dependencies: - '@types/whatwg-url': 11.0.5 - whatwg-url: 13.0.0 + mimic-response@3.1.0: {} - mongodb@6.9.0: - dependencies: - '@mongodb-js/saslprep': 1.1.9 - bson: 6.8.0 - mongodb-connection-string-url: 3.0.1 - - mongoose@8.7.0: - dependencies: - bson: 6.8.0 - kareem: 2.6.3 - mongodb: 6.9.0 - mpath: 0.9.0 - mquery: 5.0.0 - ms: 2.1.3 - sift: 17.1.3 - transitivePeerDependencies: - - '@aws-sdk/credential-providers' - - '@mongodb-js/zstd' - - gcp-metadata - - kerberos - - mongodb-client-encryption - - snappy - - socks - - supports-color + minimist@1.2.8: {} - mpath@0.9.0: {} - - mquery@5.0.0: - dependencies: - debug: 4.3.7 - transitivePeerDependencies: - - supports-color + mkdirp-classic@0.5.3: {} mrmime@2.0.0: {} @@ -2566,17 +2612,23 @@ snapshots: mute-stdout@2.0.0: {} - nanoid@3.3.7: {} + nanoid@3.3.8: {} + + napi-build-utils@1.0.2: {} negotiator@0.6.3: {} + node-abi@3.71.0: + dependencies: + semver: 7.6.3 + normalize-path@3.0.0: {} now-and-later@3.0.0: dependencies: once: 1.4.0 - object-inspect@1.13.2: {} + object-inspect@1.13.3: {} object.defaults@1.1.0: dependencies: @@ -2615,30 +2667,48 @@ snapshots: dependencies: path-root-regex: 0.1.2 - path-to-regexp@0.1.10: {} + path-to-regexp@0.1.12: {} pathe@1.1.2: {} pathval@2.0.0: {} - picocolors@1.1.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} picomatch@4.0.2: {} - postcss@8.4.47: + postcss@8.4.49: dependencies: - nanoid: 3.3.7 - picocolors: 1.1.0 + nanoid: 3.3.8 + picocolors: 1.1.1 source-map-js: 1.2.1 + prebuild-install@7.1.2: + dependencies: + detect-libc: 2.0.3 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.71.0 + pump: 3.0.2 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 ipaddr.js: 1.9.1 - punycode@2.3.1: {} + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 qs@6.13.0: dependencies: @@ -2655,6 +2725,13 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -2694,26 +2771,29 @@ snapshots: reusify@1.0.4: {} - rollup@4.24.0: + rollup@4.28.1: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.24.0 - '@rollup/rollup-android-arm64': 4.24.0 - '@rollup/rollup-darwin-arm64': 4.24.0 - '@rollup/rollup-darwin-x64': 4.24.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 - '@rollup/rollup-linux-arm-musleabihf': 4.24.0 - '@rollup/rollup-linux-arm64-gnu': 4.24.0 - '@rollup/rollup-linux-arm64-musl': 4.24.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 - '@rollup/rollup-linux-riscv64-gnu': 4.24.0 - '@rollup/rollup-linux-s390x-gnu': 4.24.0 - '@rollup/rollup-linux-x64-gnu': 4.24.0 - '@rollup/rollup-linux-x64-musl': 4.24.0 - '@rollup/rollup-win32-arm64-msvc': 4.24.0 - '@rollup/rollup-win32-ia32-msvc': 4.24.0 - '@rollup/rollup-win32-x64-msvc': 4.24.0 + '@rollup/rollup-android-arm-eabi': 4.28.1 + '@rollup/rollup-android-arm64': 4.28.1 + '@rollup/rollup-darwin-arm64': 4.28.1 + '@rollup/rollup-darwin-x64': 4.28.1 + '@rollup/rollup-freebsd-arm64': 4.28.1 + '@rollup/rollup-freebsd-x64': 4.28.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.28.1 + '@rollup/rollup-linux-arm-musleabihf': 4.28.1 + '@rollup/rollup-linux-arm64-gnu': 4.28.1 + '@rollup/rollup-linux-arm64-musl': 4.28.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.28.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.28.1 + '@rollup/rollup-linux-riscv64-gnu': 4.28.1 + '@rollup/rollup-linux-s390x-gnu': 4.28.1 + '@rollup/rollup-linux-x64-gnu': 4.28.1 + '@rollup/rollup-linux-x64-musl': 4.28.1 + '@rollup/rollup-win32-arm64-msvc': 4.28.1 + '@rollup/rollup-win32-ia32-msvc': 4.28.1 + '@rollup/rollup-win32-x64-msvc': 4.28.1 fsevents: 2.3.3 safe-buffer@5.2.1: {} @@ -2727,6 +2807,8 @@ snapshots: semver@6.3.1: optional: true + semver@7.6.3: {} + send@0.19.0: dependencies: debug: 2.6.9 @@ -2759,24 +2841,30 @@ snapshots: define-data-property: 1.1.4 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 + get-intrinsic: 1.2.5 + gopd: 1.2.0 has-property-descriptors: 1.0.2 setprototypeof@1.2.0: {} side-channel@1.0.6: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.2 - - sift@17.1.3: {} + get-intrinsic: 1.2.5 + object-inspect: 1.13.3 siginfo@2.0.0: {} - sirv@2.0.4: + simple-concat@1.0.1: {} + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + + sirv@3.0.0: dependencies: '@polka/url': 1.0.0-next.28 mrmime: 2.0.0 @@ -2786,15 +2874,11 @@ snapshots: sparkles@2.1.0: {} - sparse-bitfield@3.0.3: - dependencies: - memory-pager: 1.5.0 - stackback@0.0.2: {} statuses@2.0.1: {} - std-env@3.7.0: {} + std-env@3.8.0: {} stream-composer@1.0.2: dependencies: @@ -2824,6 +2908,8 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-json-comments@2.0.1: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -2834,6 +2920,21 @@ snapshots: optionalDependencies: semver: 6.3.1 + tar-fs@2.1.1: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.2 + tar-stream: 2.2.0 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + teex@1.0.1: dependencies: streamx: 2.18.0 @@ -2844,14 +2945,14 @@ snapshots: tinybench@2.9.0: {} - tinyexec@0.3.0: {} + tinyexec@0.3.1: {} - tinyglobby@0.2.9: + tinyglobby@0.2.10: dependencies: - fdir: 6.4.0(picomatch@4.0.2) + fdir: 6.4.2(picomatch@4.0.2) picomatch: 4.0.2 - tinypool@1.0.1: {} + tinypool@1.0.2: {} tinyrainbow@1.2.0: {} @@ -2869,16 +2970,16 @@ snapshots: totalist@3.0.1: {} - tr46@4.1.1: + tunnel-agent@0.6.0: dependencies: - punycode: 2.3.1 + safe-buffer: 5.2.1 type-is@1.6.18: dependencies: media-typer: 0.3.0 mime-types: 2.1.35 - typescript@5.6.2: {} + typescript@5.7.2: {} unc-path-regex@0.1.2: {} @@ -2891,10 +2992,10 @@ snapshots: last-run: 2.0.0 undertaker-registry: 2.0.0 - undici-types@5.26.5: {} - undici-types@6.19.8: {} + undici-types@6.20.0: {} + unpipe@1.0.0: {} util-deprecate@1.0.2: {} @@ -2946,12 +3047,13 @@ snapshots: replace-ext: 2.0.0 teex: 1.0.1 - vite-node@2.1.2(@types/node@22.7.4): + vite-node@2.1.8(@types/node@22.10.1): dependencies: cac: 6.7.14 - debug: 4.3.7 + debug: 4.4.0 + es-module-lexer: 1.5.4 pathe: 1.1.2 - vite: 5.4.8(@types/node@22.7.4) + vite: 5.4.11(@types/node@22.10.1) transitivePeerDependencies: - '@types/node' - less @@ -2963,39 +3065,40 @@ snapshots: - supports-color - terser - vite@5.4.8(@types/node@22.7.4): + vite@5.4.11(@types/node@22.10.1): dependencies: esbuild: 0.21.5 - postcss: 8.4.47 - rollup: 4.24.0 + postcss: 8.4.49 + rollup: 4.28.1 optionalDependencies: - '@types/node': 22.7.4 + '@types/node': 22.10.1 fsevents: 2.3.3 - vitest@2.1.2(@types/node@22.7.4)(@vitest/ui@2.1.2): - dependencies: - '@vitest/expect': 2.1.2 - '@vitest/mocker': 2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@22.7.4)) - '@vitest/pretty-format': 2.1.2 - '@vitest/runner': 2.1.2 - '@vitest/snapshot': 2.1.2 - '@vitest/spy': 2.1.2 - '@vitest/utils': 2.1.2 - chai: 5.1.1 - debug: 4.3.7 - magic-string: 0.30.11 + vitest@2.1.8(@types/node@22.10.1)(@vitest/ui@2.1.8): + dependencies: + '@vitest/expect': 2.1.8 + '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.1)) + '@vitest/pretty-format': 2.1.8 + '@vitest/runner': 2.1.8 + '@vitest/snapshot': 2.1.8 + '@vitest/spy': 2.1.8 + '@vitest/utils': 2.1.8 + chai: 5.1.2 + debug: 4.4.0 + expect-type: 1.1.0 + magic-string: 0.30.14 pathe: 1.1.2 - std-env: 3.7.0 + std-env: 3.8.0 tinybench: 2.9.0 - tinyexec: 0.3.0 - tinypool: 1.0.1 + tinyexec: 0.3.1 + tinypool: 1.0.2 tinyrainbow: 1.2.0 - vite: 5.4.8(@types/node@22.7.4) - vite-node: 2.1.2(@types/node@22.7.4) + vite: 5.4.11(@types/node@22.10.1) + vite-node: 2.1.8(@types/node@22.10.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.7.4 - '@vitest/ui': 2.1.2(vitest@2.1.2) + '@types/node': 22.10.1 + '@vitest/ui': 2.1.8(vitest@2.1.8) transitivePeerDependencies: - less - lightningcss @@ -3007,13 +3110,6 @@ snapshots: - supports-color - terser - webidl-conversions@7.0.0: {} - - whatwg-url@13.0.0: - dependencies: - tr46: 4.1.1 - webidl-conversions: 7.0.0 - which@1.3.1: dependencies: isexe: 2.0.0 diff --git a/Server/src/config.ts b/Server/src/config.ts index 6140c54..d50f965 100644 --- a/Server/src/config.ts +++ b/Server/src/config.ts @@ -4,20 +4,22 @@ import { defaultConfig, Config, ConfigValue } from "../../Share/Config.js"; import path from "node:path"; import fs from "node:fs/promises"; import { isValidPermissionString } from '../../Share/Permission.js'; -import { settings } from './db.js'; +import db from './db.js'; import { IDs } from '../../Share/Logging.js'; import { exists } from "./util/exists.js"; import { type AllowedSoftware, allowedSoftwares } from "../../Share/Server.js"; import isValidMCVersion from "./util/isValidMCVersion.js"; +const getFromDBQuery = db.prepare(`SELECT value FROM settings WHERE key=?`); +const updateSetting = db.prepare(`INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)`); export async function getSetting(key: keyof typeof defaultConfig, ignoreForcedChangeConfig?: boolean, errorIfNotSet?: boolean): Promise { let cachedSetting = cachedSettings[key]; if (typeof cachedSetting != "undefined" && !errorIfNotSet) { return cachedSetting; } - let databaseOption = await settings.findOne({ key }); + let databaseOption = getFromDBQuery.get(key) as {value: string, key: string}; if (!databaseOption?.value) { if (errorIfNotSet) throw new Error(key + " must be set in the settings!"); - if (forcedChangeConfig.includes(key) && !ignoreForcedChangeConfig) throw new Error(key + " must be set in the settings!"); + if (forcedChangeConfig.includes(key) && !ignoreForcedChangeConfig && process.env.IS_DOCKER != "1") throw new Error(key + " must be set in the settings!"); if (!(key in defaultConfig)) throw new Error("Invalid config key"); cachedSettings[key] = defaultConfig[key as keyof typeof defaultConfig]; return defaultConfig[key as keyof typeof defaultConfig]; @@ -42,15 +44,16 @@ If it returns an error, it will fail. */ let validators: { [key in keyof Config]?: (value: string) => Promise } = { serverPath: async (value) => { + if(process.env.IS_DOCKER == "1" && value != "/servers/") throw new Error("Changing server path isn't allowed in docker!"); if (!value) throw new Error("Server path cannot be empty"); let newPath = path.normalize(value); newPath = path.normalize(value); if (!path.isAbsolute(newPath)) throw new Error("Server path is not absolute."); // Ensure the folder exists, but is empty - if (!(await (await fs.stat(newPath)).isDirectory())) { + if (!(await fs.stat(newPath)).isDirectory()) { throw new Error("Server path is not a directory: " + newPath); } - if (await (await fs.readdir(newPath)).length != 0) { + if ((await fs.readdir(newPath)).length != 0) { throw new Error("Server path is not empty: " + newPath); } return path.normalize(newPath); @@ -119,7 +122,8 @@ export async function setSetting(key: K, value: Config[K } if (typeof value !== typeof defaultConfig[key as keyof typeof defaultConfig]) throw new Error("Invalid config value. Expected " + typeof defaultConfig[key as keyof typeof defaultConfig] + " but got " + typeof value); // Set it in the database with upsert - await settings.upsert({key}, {value: value.toString()}); + // await settings.upsert({key}, {value: value.toString()}); + updateSetting.run(key, value.toString()); cachedSettings[key] = value; if(afterSetList[key]) afterSetList[key].forEach(cb => cb(value)); return value; diff --git a/Server/src/db.ts b/Server/src/db.ts index 4077ea1..f4c6cdb 100644 --- a/Server/src/db.ts +++ b/Server/src/db.ts @@ -1,239 +1,45 @@ -import mongoose from 'mongoose'; -import nodeCrypto from 'node:crypto'; -import url from "node:url"; -import fs from "node:fs/promises"; -import path from "node:path"; -import { exists } from './util/exists.js'; -import DatabaseProvider, { DatabaseSchema, DatabaseType } from './db/databaseProvider.js'; -import JSONDatabaseProvider from './db/json.js'; -import { User } from '../../Share/User.js'; -import { Server } from '../../Share/Server.js'; -import MongoDatabaseProvider from './db/mongo.js'; -// use mongoose unless u want to pain urself -mongoose.set("strictQuery", false); -if(process.env.BURGERPANEL_MONGOOSE_DEBUG) mongoose.set("debug", true) -let __dirname = url.fileURLToPath(new URL('.', import.meta.url)); -let mongoURL = process.env.BURGERPANEL_MONGODB; -if(!mongoURL) mongoURL = process.env.DB; -// If not found it will search up to 5 folders for mongodb_url.txt -if(!mongoURL) { - let searchingPath = __dirname; - for(let i = 0; i < 5; i++) { - let pathToSearch = path.join(searchingPath, "mongodb_url.txt") - if(await exists(pathToSearch)) { - mongoURL = (await fs.readFile(pathToSearch)).toString().trim(); // set the mongodb url to the file contents and trim it - break; - } - searchingPath = path.join(searchingPath, ".."); - } +import Sqlite from "better-sqlite3"; +import { migrations } from "./migrations.js"; +import fs from "node:fs"; +import logger, { LogLevel } from "./logger.js"; +import type { User } from "../../Share/User"; +import { Server } from "../../Share/Server"; +import { exists } from "./util/exists.js"; +if(process.env.IS_DOCKER == "1" && !await exists("/db/")) { + logger.log("/db/ isnt mounted in docker!", "error", LogLevel.ERROR); + process.exit(1); } -if(!mongoURL) { - throw new Error("Unable to find mongodb url, searched for env vars BURGERPANEL_MONGODB and DB, and file mongodb_url.txt for 5 folders.\n" + - "If you don't want to set up a mongo server you can set it to `json:path` to store it in JSON files (unrecommended for big servers)"); +const dbPath = process.env.IS_DOCKER == "1" ? "/db/burgerpanel.sqlite3" : "burgerpanel.sqlite3"; +const db = new Sqlite(dbPath, { + verbose: (data) => { + /*if(process.env.NODE_ENV != "production")*/ logger.log("SQL: " + data, "debug", LogLevel.DEBUG); + }, + nativeBinding: process.env.IS_DOCKER == "1" ? "/panel/better_sqlite3.node" : undefined +}); +db.pragma('journal_mode = WAL'); // speeeeed +db.exec(`CREATE TABLE IF NOT EXISTS migrations (id INTEGER PRIMARY KEY AUTOINCREMENT, version TEXT UNIQUE NOT NULL, applied_at DATETIME DEFAULT CURRENT_TIMESTAMP)`); +// Migrate!!! +const unappliedMigrations: string[] = []; +const checkAppliedMigration = db.prepare("SELECT applied_at FROM migrations WHERE version = ?"); +const insertMigration = db.prepare("INSERT INTO migrations (version) VALUES (?)"); +Object.keys(migrations).forEach(migration => { + if(!checkAppliedMigration.get(migration)) unappliedMigrations.push(migration); +}); +if(unappliedMigrations.length != 0) { + logger.log(`Missing migrations: ${JSON.stringify(unappliedMigrations)}. Backing up database...`, "info"); + await db.backup(dbPath + ".bak-" + Date.now()); + logger.log("Backup complete", "info"); + unappliedMigrations.forEach(migration => { + migrations[migration].forEach(migrationData => { + logger.log(`Applying migration ${migration}`, "debug", LogLevel.DEBUG); + db.exec(migrationData); + }); + insertMigration.run(migration); + }); } -let databaseManager = new class DatabaseManager { - databaseProvider: DatabaseProvider; - constructor() { - if(mongoURL?.startsWith("json:")) this.databaseProvider = new JSONDatabaseProvider(mongoURL.replace("json:", "")); - else this.databaseProvider = new MongoDatabaseProvider(mongoURL as string); - } - async _init() { - await this.databaseProvider.init(); - } - collection(name: string, schema: DatabaseSchema, mongooseSchema: mongoose.Schema) { - return this.databaseProvider.getCollection(name, schema, mongooseSchema); - } -} -await databaseManager._init(); - -export let makeToken = () => nodeCrypto.randomBytes(64).toString("base64url"); -export let users = databaseManager.collection("User", { - _id: {type: "String"}, - username: {type: "String"}, - createdAt: {type: "Date", default: Date.now}, - permissions: [{type: "String", default: []}], - setupPending: {type: "boolean", default: true}, - token: {type: "String", default: makeToken}, - devMode: {type: "boolean", default: false}, - password: {type: "String"}, - pins: [{type: "String", default: []}] -}, new mongoose.Schema({ - username: { - type: String, - unique: true, - maxlength: 24, - required: true - }, - createdAt: { type: Date, default: Date.now }, - token: { - type: String, - default: makeToken - }, - permissions: { - type: [String], - default: [] - }, - password: { - type: String - }, - setupPending: { - type: Boolean, - default: true - }, - devMode: { - type: Boolean, - required: false, - default: false - }, - pins: [{ - type: String, - max: 3, - default: [], - validate: [(v: any) => v.length >= 10, "Too many pinned servers"] - }] -})); - -export let servers = databaseManager.collection("Server", { - name: { - type: "String", - unique: true, - maxlength: 16, - required: true - }, - path: { - type: "String", - unique: true, - maxlength: 255, - required: true - }, - mem: { - type: "number", - min: 0, - max: 99999, - required: true - }, - jvmArgs: { - type: "String", - maxlength: 99999, - required: false - }, - allowedUsers: [{ - user: {type: "String"}, - permissions: [{type: "String"}], - }], - version: { - type: "String", - maxlength: 16, - required: true - }, - software: { - type: "String", - maxlength: 7, - required: true - }, - port: { - min: 1, - max: 65535, - type: "number", - unique: true, - required: true - }, - autoStart: { - type: "boolean", - default: false - }, - autoRestart: { - type: "boolean", - default: false - }, - useCustomJVMArgs: { - type: "boolean", - default: false - }, - _id: { - type: "String" - } -}, new mongoose.Schema({ - name: { - type: String, - unique: true, - maxlength: 16, - required: true - }, - path: { - type: String, - unique: true, - maxlength: 255, - required: true - }, - mem: { - type: Number, - min: 0, - max: 99999, - required: true - }, - allowedUsers: [{ - user: String, - permissions: [String], - /*roles: [mongoose.Types.ObjectId]*/ - }], - version: { - type: String, - maxlength: 16, - required: true - }, - software: { - type: String, - maxlength: 7, - required: true - }, - port: { - min: 1, - max: 65535, - type: Number, - unique: true, - required: true - }, - autoStart: { - type: Boolean, - default: false - }, - autoRestart: { - type: Boolean, - default: false - }, - jvmArgs: { - type: String, - default: "", - maxlength: 2000 - }, - useCustomJVMArgs: { - type: Boolean, - default: false - } -})); - -export let settings = databaseManager.collection<{_id: string, key: string, value: string}>("Setting", { - key: { - type: "String", - unique: true, - maxlength: 255, - }, - value: { - type: "String", - maxlength: 1000, - }, - _id: { - type: "String" - } -}, new mongoose.Schema({ - key: { - type: String, - unique: true, - maxlength: 255, - }, - value: { - type: String, - maxlength: 1000, - }, -})); \ No newline at end of file +export const getUserByToken: Sqlite.Statement = db.prepare(`SELECT * FROM users WHERE token=? LIMIT 1`); +export const getUserByID: Sqlite.Statement<(number | string)[], User> = db.prepare(`SELECT * FROM users WHERE id=? LIMIT 1`); +export const getServerByID: Sqlite.Statement<(number | string | bigint)[], Server> = db.prepare(`SELECT * FROM servers WHERE id=? LIMIT 1`); +export const getServerByName: Sqlite.Statement = db.prepare(`SELECT * FROM servers WHERE name=? LIMIT 1`); +export const getServerPermissions_UID_SID = db.prepare("SELECT permissions FROM user_server_access WHERE user_id=? AND server_id=?"); +export default db; \ No newline at end of file diff --git a/Server/src/db/databaseProvider.ts b/Server/src/db/databaseProvider.ts deleted file mode 100644 index ebf28af..0000000 --- a/Server/src/db/databaseProvider.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type mongoose from "mongoose"; -import type { JSONCollection } from "./json.js"; -import type { MongooseCollection } from "./mongo.js"; -export default class DatabaseProvider { - constructor() { - - } - async init() {this._unImplemented()} - private _unImplemented() { - throw new Error("Uninplemented database function!"); - } - // @ts-expect-error - getCollection(name: string, schema: DatabaseSchema, mongooseSchema: mongoose.Schema): Collection {this._unImplemented()} -} -export type DatabaseLookupFilter = Partial -export class Collection { - constructor(name: string, databaseProvider: DatabaseProvider) {} - find(filter: DatabaseLookupFilter, limit: number = 50): Promise[]> {this._unImplemented()} - findOne(filter: DatabaseLookupFilter): Promise> {this._unImplemented()} - findById(id: string): Promise> {this._unImplemented()} - deleteById(id: string): Promise {this._unImplemented()} - getAll(): Promise[]> {this._unImplemented()} - private _unImplemented(): never { - throw new Error("Uninplemented database function!"); - } - isJSONCollection(): this is JSONCollection {return false} - isMongoDBDatabaseProvider(): this is MongooseCollection {return false} - create(data: Partial>): Promise> {this._unImplemented()} - upsert(findBy: DatabaseLookupFilter, newData: Partial>): Promise {this._unImplemented()} - countDocuments(filter: DatabaseLookupFilter): Promise {this._unImplemented()} - findByIdAndUpdate(id: string, newData: Partial>): Promise {this._unImplemented()} -} -export type DatabaseType = { - _id: string -} -export type DatabaseObject = T & { - delete: () => Promise, - save: () => Promise, - toJSON: () => T, - deleteOne: () => Promise -} -export type DatabaseSchemaInnerType = { - type: "Date" | "String" | "number" | "boolean", - required?: boolean, // defaults to false - unique?: boolean, // defaults to false - maxlength?: number, - max?: number, - min?: number, - default?: any -} -export type DatabaseSchema = { - [name in keyof T]: DatabaseSchemaInnerType | [DatabaseSchemaInnerType] | [{[key: string]: DatabaseSchemaInnerType | [DatabaseSchemaInnerType]}] -}; -export function isFollowingSchema(obj: DatabaseObject, schema: DatabaseSchema) { - return true; // TODO: fix -} \ No newline at end of file diff --git a/Server/src/db/json.ts b/Server/src/db/json.ts deleted file mode 100644 index d0db2c0..0000000 --- a/Server/src/db/json.ts +++ /dev/null @@ -1,239 +0,0 @@ -// I am really sorry for writing this absolute mess -// It works, so please do not touch it. -// unrecommended for large servers -import DatabaseProvider, { Collection, DatabaseLookupFilter, DatabaseObject, DatabaseSchema, DatabaseSchemaInnerType, DatabaseType } from "./databaseProvider.js" -import path from "node:path"; -import url from "node:url"; -import fsSync from "node:fs"; -import { exists } from "../util/exists.js"; -import nodeCrypto from "node:crypto"; -const isProd = process.env.NODE_ENV == "production"; -let __dirname = url.fileURLToPath(new URL('.', import.meta.url)); -type JSONStructure = { - [collection: string]: any[]; -} -export default class JSONDatabaseProvider extends DatabaseProvider { - path: string; - currentFullJSON: JSONStructure = {}; - constructor(path: string) { - super(); - this.path = path; - } - async init() { - if(!path.isAbsolute(this.path)) this.path = path.join(isProd ? __dirname : process.cwd(), this.path); - try { - if(!await exists(this.path)) fsSync.writeFileSync(this.path, "{}"); - let data = (await fsSync.readFileSync(this.path)).toString(); - this.currentFullJSON = JSON.parse(data); - } catch(err) { - throw new Error(`Cannot load '${this.path}': ${err}`); - } - } - getCollection(name: string, schema: DatabaseSchema) { - return new JSONCollection(name, schema, this); - } - async saveJSON() { - await fsSync.writeFileSync(this.path, JSON.stringify(this.currentFullJSON, null, 2)); - } -} -export class JSONCollection extends Collection { - databaseProvider: JSONDatabaseProvider; - name: string; - schema: DatabaseSchema; - constructor(name: string, schema: DatabaseSchema, databaseProvider: JSONDatabaseProvider) { - super(name, databaseProvider); - if(typeof databaseProvider.currentFullJSON[name] != "object") databaseProvider.currentFullJSON[name] = []; - this.databaseProvider = databaseProvider; - this.name = name; - this.schema = schema; - } - private getCurrentData(): T[] { - return this.databaseProvider.currentFullJSON[this.name]; - } - async find(filter: DatabaseLookupFilter, limit: number = 50): Promise[]> { - let data = this.getCurrentData(); - if(Object.keys(filter).length == 0) throw new Error("empty filter, do you want .getAll()?"); - let matched = data; - for(let key of Object.keys(filter)) { - matched = matched.filter(m => m[key as keyof T] == filter[key as keyof T]); - } - // limit is kinda useless when doing this way but for compatibility its needed - matched = matched.slice(0, limit); - return matched.map(match => this.createDatabaseObject(match)); - } - async findOne(filter: DatabaseLookupFilter) { - return (await this.find(filter, 1))[0]; - } - async findById(id: string): Promise> { - // @ts-ignore - let found = await this.find({_id: id}); - return found[0]; - } - private createDatabaseObject(obj: T): DatabaseObject { - if(!obj?._id) throw new Error("Missing _id"); - let that = this; - let newObj = { - ...obj, - async delete() { - await that.deleteById(obj._id); - }, - async deleteOne() { - await newObj.delete(); - }, - async save() { - await that.assertsFollowsSchema(this.toJSON()); - await this.delete(); - await that.insert(this.toJSON()); - }, - toJSON() { - let newObj = {}; - for(let _key of Object.keys(this)) { - let key = _key as keyof DatabaseObject; - if(this[key] instanceof Function) continue; - // @ts-ignore i cant bother - newObj[key] = this[key]; - } - return newObj as T; - } - } - return newObj; - } - private insert(obj: T) { - this.assertsFollowsSchema(obj); - this.databaseProvider.currentFullJSON[this.name].push(obj); - this.databaseProvider.saveJSON(); - } - async deleteById(id: string) { - this.databaseProvider.currentFullJSON[this.name] = this.databaseProvider.currentFullJSON[this.name].filter(obj => obj?._id != id); - await this.databaseProvider.saveJSON(); - } - isJSONCollection(): this is JSONCollection { - return true; - } - async getAll(): Promise[]> { - return this.getCurrentData().map(obj => this.createDatabaseObject(obj)); - } - async create(data: Partial>): Promise> { - let newData = this.bootstrapNecessaryTypes(data); - await this.assertsFollowsSchema(newData); - this.insert(newData); - return this.createDatabaseObject(newData); - } - async assertsFollowsSchema(data: T, schema: DatabaseSchema = this.schema): Promise { - for await(let key of Object.keys(schema)) { - let obj = schema[key as keyof typeof schema]; - if(Array.isArray(obj)) { - // @ts-ignore - for await(let dObj of Object.values(data[key] ?? [])) { - try { - await this.assertsFollowsSchema({ - _id:"A", - __: dObj - // @ts-ignore - } as any as T, {_id:{type:"String"},__: obj[0]}); - } catch(err) { - throw new Error(`Cannot validate object in array .${key}: ${(err as Error).message ?? err}`); - } - } - } else { - // @ts-ignore - let databaseObj: any = data[key]; - if(obj.required) { - if(typeof databaseObj == "undefined") throw new Error(`.${key} is undefined when its required`); - } else { - if(typeof databaseObj == "undefined") continue; - } - if(obj.unique) { - if(schema != this.schema) throw new Error("Unique isnt allowed in arrays"); - // @ts-ignore - let foundItems = await this.find({[key as keyof typeof T]: databaseObj}); - let foundItemsWithoutSameID = foundItems.filter(a => a._id != data._id); - if(foundItemsWithoutSameID.length) throw new Error(`.${key} isnt unique!`); - } - if(obj.type == "number") { - if(typeof databaseObj != "number") { - // try making it a number - let newNum = Number(databaseObj); - if(isNaN(newNum)) throw new Error(`.${key} isnt a number when type is`); - databaseObj = newNum; - } - if(isNaN(databaseObj)) throw new Error(`.${key} is nan`); - if(typeof obj.max == "number" && databaseObj > obj.max) throw new Error(`.${key} is too big (${databaseObj}) when ${obj.max} is max`); - if(typeof obj.min == "number" && databaseObj < obj.min) throw new Error(`.${key} is too small (${databaseObj}) when ${obj.min} is min`); - } else if(obj.type == "String") { - if(typeof databaseObj != "string") throw new Error(`.${key} isnt a string when type is`); - if(typeof obj.maxlength == "number" && databaseObj.length > obj.maxlength) throw new Error(`String .${key} is too long!`); - } else if(obj.type == "Date") { - if(typeof databaseObj != "number" || !Number.isInteger(databaseObj)) throw new Error(`.${key} is supposed to be a number because it's a date but it isnt`); - } else if(obj.type == "boolean") { - if(typeof databaseObj != "boolean") throw new Error(`.${key} isnt a boolean when its supposed to be one!`); - } - } - } - } - bootstrapNecessaryTypes(data: Partial>, schema: DatabaseSchema = this.schema, includeID: boolean = true): T { - let newData: any = {}; - Object.keys(data).forEach(key => { - newData[key] = data[key as keyof typeof data]; - }); - Object.keys(schema).forEach((key) => { - if(Array.isArray(schema[key as keyof typeof schema])) { - // @ts-ignore - let insideArr: any = schema[key as keyof typeof schema][0]; - if(typeof insideArr?.type == "string") { - // @ts-ignore - newData[key] = this.bootstrapNecessaryTypes({__:data[key]} ?? {}, {__: schema[key as keyof typeof schema][0]}).__; - } else { - // @ts-ignore - newData[key] = Object.values(this.bootstrapNecessaryTypes(data[key] ?? {}, insideArr, false)); - newData[key] = newData[key].filter((a: any) => a != undefined); // this is the most stupid fix for it randomly being null but it works so idc - } - } else { - if((schema[key as keyof typeof schema] as DatabaseSchemaInnerType)?.default && typeof data[key as keyof typeof data] == "undefined") { - if((schema[key as keyof typeof schema] as DatabaseSchemaInnerType).default instanceof Function) { - newData[key] = (schema[key as keyof typeof schema] as DatabaseSchemaInnerType).default() - } else { - newData[key] = (schema[key as keyof typeof schema] as DatabaseSchemaInnerType).default - } - } - } - }); - if(includeID && typeof newData._id == "undefined") newData._id = this.findUnusedID(); - return newData; - } - private findUnusedID() { - let all = this.getCurrentData(); - while(true) { - let id = nodeCrypto.randomBytes(10).toString("hex"); - if(!all.some(a => a._id == id)) return id; - } - } - async upsert(findBy: Partial, newData: Partial>) { - let obj = await this.findOne(findBy); - if(!obj) { - this.create({ - ...findBy, - ...newData - }); - return; - } else { - for(let key of Object.keys(newData)) { - // @ts-ignore - obj[key as keyof typeof obj] = newData[key as keyof typeof newData]; - } - await obj.save(); - } - } - async countDocuments(filter: Partial): Promise { - if(Object.keys(filter).length == 0) return (await this.getAll()).length; - return (await this.find(filter)).length; - } - async findByIdAndUpdate(id: string, newData: Partial>): Promise { - let obj = await this.findById(id); - for(let key of Object.keys(newData)) { - // @ts-ignore - obj[key as keyof typeof obj] = newData[key as keyof typeof newData]; - } - await obj.save(); - } -} diff --git a/Server/src/db/mongo.ts b/Server/src/db/mongo.ts deleted file mode 100644 index d005fce..0000000 --- a/Server/src/db/mongo.ts +++ /dev/null @@ -1,58 +0,0 @@ -import mongoose, { Mongoose } from "mongoose"; -import DatabaseProvider, { Collection, DatabaseObject, DatabaseSchema, DatabaseType } from "./databaseProvider.js"; -export default class MongoDatabaseProvider extends DatabaseProvider { - private connection: Mongoose; - private url: string; - constructor(url: string) { - super(); - this.url = url; - this.connection = mongoose; - } - async init() { - this.connection = await mongoose.connect(this.url); - } - getCollection(name: string, _: DatabaseSchema, schema: mongoose.Schema): Collection { - let coll = this.connection.model(name, schema); - return new MongooseCollection(name, this, coll); - } -} -export class MongooseCollection extends Collection { - model: mongoose.Model; - constructor(name: string, databaseProvider: MongoDatabaseProvider, model: mongoose.Model) { - super(name, databaseProvider); - this.model = model; - } - async countDocuments(filter: Partial): Promise { - return await this.model.countDocuments(filter).exec(); - } - async create(data: Partial>): Promise> { - return await this.model.create(data); - } - async deleteById(id: string): Promise { - await this.model.findByIdAndDelete(id).exec(); - } - async find(filter: Partial, limit?: number): Promise[]> { - return await this.model.find(filter, {}, {limit}).exec(); - } - isMongoDBDatabaseProvider(): this is MongooseCollection { - return true; - } - async findById(id: string): Promise> { - return await this.model.findById(id).exec(); - } - async findByIdAndUpdate(id: string, newData: Partial>): Promise { - await this.model.findByIdAndUpdate(id, newData).exec(); - } - async findOne(filter: Partial): Promise> { - return await this.model.findOne(filter).exec(); - } - async getAll(): Promise[]> { - return await this.model.find({}, {}, {limit: 10_000}); - } - async upsert(findBy: Partial, newData: Partial>): Promise { - return await this.model.findOneAndUpdate(findBy, newData, {upsert: true}).exec(); - } - get _getModel() { - return this.model; - } -} \ No newline at end of file diff --git a/Server/src/index.ts b/Server/src/index.ts index 7d40cfd..c6f447f 100644 --- a/Server/src/index.ts +++ b/Server/src/index.ts @@ -9,8 +9,8 @@ import url from "node:url"; import { afterSet, getSetting, isValidKey, setSetting } from './config.js'; import { once } from "node:events"; import serverManager from './serverManager.js'; -import { makeToken, servers, users } from './db.js'; -import { Permission } from '../../Share/Permission.js'; +import db, { getServerByID, getServerByName, getUserByToken } from './db.js'; +import { Permission, PermissionString } from '../../Share/Permission.js'; import { Request, RequestResponses } from '../../Share/Requests.js'; import hasPermission from './util/permission.js'; import logger, { LogLevel } from './logger.js'; @@ -18,6 +18,8 @@ import {buildInfo} from "../../Share/BuildInfo.js"; import pluginHandler, {mixinHandler} from "./plugin.js"; import { exists } from "./util/exists.js"; import { OurClient, OurWebsocketClient, clients } from "./clients.js"; +import { makeToken } from "./util/token.js"; +import { Server } from "../../Share/Server.js"; export const isProd = process.env.NODE_ENV == "production"; @@ -38,7 +40,7 @@ app.use(async (req, res, next) => { if(await mixinHandler.handle("httpRequest", {req, res})) return; next(); }); -app.post("/api/request/:name", async (req, res, next) => { +app.post("/api/request/:name", async (req: express.Request, res: express.Response, next: express.NextFunction) => { if(lockdownMode) return; if(!packetHandler.packets[req.params.name]) return next(); if(req.headers["content-type"] != "application/json") return res.status(400).json({ @@ -48,7 +50,7 @@ app.post("/api/request/:name", async (req, res, next) => { if(!token) return res.status(400).json({ error: "Missing token" }); - let user = await users.findOne({token}); + let user: User = await getUserByToken.get() as User; if(!user) return res.status(401).json({ error: "Invalid token" }); @@ -71,7 +73,7 @@ app.post("/api/request/:name", async (req, res, next) => { auth: { authenticated: true, token, - user: user.toJSON() + user: user }, clientID: genClientID() }, @@ -187,7 +189,7 @@ class PacketHandler { }); return; } - if(lockdownMode && lockDownExcludedUser != client.data.auth.user?._id && packet.name != "auth") return; + if(lockdownMode && lockDownExcludedUser != client.data.auth.user?.id && packet.name != "auth") return; try { let packetResponse = await packet.handle(client, data.d); if(typeof packetResponse == "string") { @@ -209,7 +211,7 @@ class PacketHandler { e: isProd ? "Internal server error. Read the server logs for more details." : `${err}`, n: data.n }); - logger.log(`Packet errored. User is ${client.data.auth?.user?.username} (${client.data.auth?.user?._id}) ${data.n} ${err}`, "error", LogLevel.ERROR); + logger.log(`Packet errored. User is ${client.data.auth?.user?.username} (${client.data.auth?.user?.id}) ${data.n} ${err}`, "error", LogLevel.ERROR); } } } @@ -233,7 +235,7 @@ export let packetHandler = new PacketHandler(); let logging = false; let loggingIgnore: string[] = []; export let lockdownMode = false; -export let lockDownExcludedUser = ""; +export let lockDownExcludedUser = -1; let clientID = 0; function genClientID() { return clientID++; @@ -368,8 +370,30 @@ async function findLogPath() { } return filePath + ".log"; } + +function createAdminUserIfNeeded() { + const hasFullPermission = db.prepare(` + SELECT 1 + FROM users + WHERE EXISTS ( + SELECT 1 + FROM json_each(users.permissions) + WHERE json_each.value = 'full' + ) + LIMIT 1 + `).get(); + + if (hasFullPermission) return; + const newUserToken = makeToken(); + db.prepare("INSERT INTO users (username, permissions, token) VALUES (?, ?, ?)").run("gen-admin-" + Date.now(), '["full"]', newUserToken); + logger.log("Created admin user with token " + newUserToken, "info", LogLevel.INFO); +} + packetHandler.init().then(async () => { logger.setupWriteStream(await findLogPath()); + if(process.env.IS_DOCKER == "1" && await getSetting("serverPath") != "/servers/") { + await setSetting("serverPath", "/servers/"); + } afterSet("logging_DisabledIDs", newVal => { logger.ignoredLogs = newVal; }); @@ -386,6 +410,10 @@ packetHandler.init().then(async () => { port = parseInt(portEnv); break portTry; } + if(process.env.IS_DOCKER == "1") { + console.log("PORT env var has to be set in docker!"); + process.exit(1); + } console.log("Port not set. Please enter a port to listen on and press enter: "); while (!port) { let data = await (await once(process.stdin, "data")).toString().trim(); @@ -403,25 +431,25 @@ packetHandler.init().then(async () => { await pluginHandler.init(); console.log("Type 'help' for help"); serverManager.autoStartServers(); + createAdminUserIfNeeded(); }); process.stdin.on("data", async (data) => { let dataStr = data.toString().trim(); switch (dataStr) { case "users-table": - var userlist = await users.getAll(); - console.table(userlist.map(u => u.toJSON()).map(u => ({ - _id: u._id.toString(), - name: u.username, - permissions: u.permissions + var userlist = db.prepare("SELECT id, username FROM users").all() as User[]; + console.table(userlist.map(u => ({ + _id: u.id, + name: u.username }))); break; case "users": case "users-list": - var userlist = await users.getAll(); + var userlist = db.prepare("SELECT * FROM users").all() as User[]; console.log("---------"); for (let user of userlist.values()) { console.log("Username: " + user.username); - console.log("ID: " + user._id); + console.log("ID: " + user.id); console.log("Token: " + user.token); console.log("Permissions: " + user.permissions); console.log("Created at: " + user.createdAt); @@ -429,27 +457,24 @@ packetHandler.init().then(async () => { } break; case "gen-admin-user": - let adminUser = await users.create({ - permissions: ["full"], - username: "gen-admin-" + Date.now(), - }); - console.log("Created admin user with ID " + adminUser._id + " and token " + adminUser.token); + const newUserToken = makeToken(); + db.prepare("INSERT INTO users (username, permissions, token) VALUES (?, ?, ?)").run("gen-admin-" + Date.now(), '["full"]', newUserToken); + console.log("Created admin user with token " + newUserToken); break; case "servers": console.log("---------"); - for (let server of await (await servers.getAll()).values()) { - console.log("Server ID: " + server._id); + const servers: Server[] = db.prepare("SELECT * FROM servers").all() as Server[]; + for (let server of servers) { + console.log("Server ID: " + server.id); console.log("Server name: " + server.name); console.log("Server port: " + server.port); console.log("Server version: " + server.version); - console.log("Server status: " + (await serverManager.servers[server._id.toString()]?.childProcess ? "Running" : "Stopped")); + console.log("Server status: " + (serverManager.servers[server.id.toString()]?.childProcess ? "Running" : "Stopped")); console.log("Server software" + server.software); console.log("Server path: " + server.path); - console.log("Server autostart: " + server.autoStart); - console.log("Allowed users: " + (await Promise.all(server.allowedUsers.map(async u => { - let userdata = await users.findById(u.user); - return userdata?.username + " (" + u.permissions.join(", ") + ")"; - }))).join(", ")); + console.log("Server autostart: " + server.autostart); + const allowedUsers = db.prepare(`SELECT users.id as uid, users.username as name, user_server_access.permissions FROM user_server_access INNER JOIN users ON user_server_access.user_id = users.id WHERE user_server_access.server_id = ?`).all(server.id) as {name: string, uid: number, permissions: string}[]; + console.log("Allowed users: " + (allowedUsers.map(allowedUser => `${allowedUser.name} (${allowedUser.uid}): ${JSON.parse(allowedUser.permissions).join(", ")}`)).join(", ")); console.log("---------"); } break; @@ -467,14 +492,6 @@ packetHandler.init().then(async () => { if(lockdownMode) clients.forEach(c => c.close()) logger.log(`Lockdown mode is now ${lockdownMode ? "enabled. Use the same command to re-enable. You may use delete-user to delete a user, gen-admin-user to make a new one and 'lockdown-exclude ' to exclude a user." : "disabled."}`, "info", LogLevel.WARNING); break; - case "lockdown-auto": - lockdownMode = true; - clients.forEach(c => c.close()) - let lockdownUser = await users.create({username: "lockdown-" + Date.now(), setupPending: false, permissions: ["full"]}); - await lockdownUser.save(); - lockDownExcludedUser = lockdownUser._id.toString(); - logger.log(`Lockdown mode has been enabled. Use this token to log in: "${lockdownUser.token}". Use a private/incognito tab if you get stuck on logging in. Use 'lockdown' to disable.`, "info", LogLevel.INFO, false); - break; case "help": console.log("users: List all users"); console.log("gen-admin-user: Generate a admin user"); @@ -483,7 +500,6 @@ packetHandler.init().then(async () => { console.log("set-opt