From 2f18f0f0964c2bf4b68041a430747e7148e01b2c Mon Sep 17 00:00:00 2001 From: Liam Date: Sat, 28 Sep 2024 05:57:35 +0100 Subject: [PATCH] wish me luck --- .env-example | 6 + .gitea/kubernetes/deployment.yaml | 26 + .gitea/kubernetes/sealed-secrets.yaml | 20 + .gitea/workflows/deploy.yml | 1 + config.ts | 2 +- package.json | 13 +- pnpm-lock.yaml | 1104 ++++++++++++++++- src/app/(pages)/api/player/history/route.ts | 45 + src/app/(pages)/api/trigger/route.ts | 10 + src/app/(pages)/page.tsx | 15 +- src/app/(pages)/player/[...slug]/page.tsx | 19 +- .../model/player/impl/scoresaber-player.ts | 57 +- src/common/mongo.ts | 12 + src/common/player-utils.ts | 128 ++ src/common/player/player-history.ts | 16 + src/common/schema/player-schema.ts | 123 ++ src/common/service/impl/scoresaber.ts | 13 +- src/common/time-utils.ts | 42 + src/common/website-utils.ts | 4 +- src/components/player/player-data.tsx | 4 +- src/components/player/player-rank-chart.tsx | 192 ++- src/components/ranking/mini.tsx | 2 +- src/jobs/index.ts | 3 + src/jobs/seed-player-statistics.ts | 33 + src/trigger.ts | 7 + 25 files changed, 1812 insertions(+), 85 deletions(-) create mode 100644 .env-example create mode 100644 .gitea/kubernetes/sealed-secrets.yaml create mode 100644 src/app/(pages)/api/player/history/route.ts create mode 100644 src/app/(pages)/api/trigger/route.ts create mode 100644 src/common/mongo.ts create mode 100644 src/common/player-utils.ts create mode 100644 src/common/player/player-history.ts create mode 100644 src/common/schema/player-schema.ts create mode 100644 src/jobs/index.ts create mode 100644 src/jobs/seed-player-statistics.ts create mode 100644 src/trigger.ts diff --git a/.env-example b/.env-example new file mode 100644 index 0000000..ecdc481 --- /dev/null +++ b/.env-example @@ -0,0 +1,6 @@ +NEXT_PUBLIC_SITE_URL=http://localhost:3000 +NEXT_PUBLIC_TRIGGER_PUBLIC_API_KEY= + +TRIGGER_API_KEY= +TRIGGER_API_URL=https://trigger.fascinated.cc +MONGO_URI=mongodb://127.0.0.1:27017 diff --git a/.gitea/kubernetes/deployment.yaml b/.gitea/kubernetes/deployment.yaml index b95a916..0b6c4cf 100644 --- a/.gitea/kubernetes/deployment.yaml +++ b/.gitea/kubernetes/deployment.yaml @@ -26,3 +26,29 @@ spec: limits: cpu: 1000m # 1 vCPU memory: 256Mi + env: + - name: MONGO_URI + valueFrom: + secretKeyRef: + name: ssr-secret + key: MONGO_URI + - name: NEXT_PUBLIC_SITE_URL + valueFrom: + secretKeyRef: + name: ssr-secret + key: NEXT_PUBLIC_SITE_URL + - name: NEXT_PUBLIC_TRIGGER_PUBLIC_API_KEY + valueFrom: + secretKeyRef: + name: ssr-secret + key: NEXT_PUBLIC_TRIGGER_PUBLIC_API_KEY + - name: TRIGGER_API_KEY + valueFrom: + secretKeyRef: + name: ssr-secret + key: TRIGGER_API_KEY + - name: TRIGGER_API_URL + valueFrom: + secretKeyRef: + name: ssr-secret + key: TRIGGER_API_URL diff --git a/.gitea/kubernetes/sealed-secrets.yaml b/.gitea/kubernetes/sealed-secrets.yaml new file mode 100644 index 0000000..0068ee9 --- /dev/null +++ b/.gitea/kubernetes/sealed-secrets.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + creationTimestamp: null + name: ssr-secret + namespace: public-services +spec: + encryptedData: + MONGO_URI: AgBSW/TeDuqMDd4JslZ0MjBkX/vYxjicHN/4F/CRLOurmeWKQymrXqYEAvpdWv9pn3OcbzsBU152+NNRMM87lmMbsv4PS1v4X3Apc/5isL81CD3HXvs5o8ls9XNUvR3vriZI1ZzfQOKmLW81gqefCtAMkEOWI/RW3mj7Ai8C3kHve+RX26Ncevi3/af6VrHU6bFVwOshRFlZlPIqTbo0Y6V1S7bWtgeAkiahPNsru4jFozbBa19T131OHAud1v6UL8eyXz4OU7NMWtkztarNdOaAL/RQFxzP3ievVGW4YXLkWiXac1YQnTynxODUlm+piY7mN4KCkX4cIPDQ/jTBU54NtWuy/zrmscw5LK4WheuwkdqWWOZRxoDg+5Q/RwtZeuT7GkDQQPKmH6ti1vrXt4tF1BbW35uFbwC2fKeovm1VVtmPlY2pPy10HANKOpHhpMMazvhtj+pcuKICTXCC4D0ccJUgrYx5zuqXKKZOVqw1RxwwXQDJ1ooldmuKrWLxYu1kRe7CkA3yzT9lWTbRThsxl91cXGcT+G6ZfiSS8I/0Y+1XUyYCKmszd55KnBMZvRe3TohdUugap7TIYiKUAYQ272zdN2jxzeWb5IWqLp2RETl8a3DpQKaUCRnQQtUoipEIStJDhYQwITF6OsTg0W49eHA5NtC8TkXdOy0vvZnim6jXT6Rv5R9aXg3yFFjb2dAgPwcoYLv6snnjedA35quY7WpCwJegoF9NbZOQcvrjxVaFASPg53B/g7V3wHl4t+g2pbiZ2j4/6VbVVnhP1GlhcMbbynGEgr8yGK8V0xbxRfJFqS39YwgxL+M= + NEXT_PUBLIC_SITE_URL: AgAN582ssfWgQ58zWHBGTCG4v5okX1tMsc0ssnXBfO8uIk3XV6B/Wct/FO2HupaBBqiRf5ngWK45Zl4i4RKd2suiWXPRniwe8SpRreNECrqXiFH103hJHYxDIy3oR+wMjB2Wzj9HmyiqpdMtnqw61j9qNqPyu0yyXgqLIIBeL21jkXuHhJtjD9In8JvxI4qh+9LrKJGAJhgR7H48+PCvrN1YLJGthVu1A8M0TkfZGYv3yKSsp+18WbdDT4LH9pJLuymgUaAC28xJXIo69lP43mdxgK1Oc4icRLnO9CTA5otZ94n5bSadZHsM+SEFDkAk2sTpRbehw0/qxM/DFaDC4CgWbSi9fJF4O5bKGHWRvQ/l4sQkj6xdvcGMUgB1f2s4sGZijlFTGdCxaMb83TL8PZjjhcglc2/E7YMlLXP5NkuVYxO4Mb8ZPMbZ4DQBASSW0YK9XF3UeZnTMXtcNioUDyACvIcaJudRSHJQZFdaV1eWfdz+Nv0uGoin3PpxRCV8Qx9O3GJ5IHdJGTGZrh0P+kX7vlv3Y/AVc7BttuiIDkxKQBBW3MXatccTJu+ML5beI88VLKCoSTQiYc+0WrvLchGhWAu/56IgGxwtteQP4sTPJnr3L/5VmUN6YeyFHcHvXplivjv+ofnMTnytWH1FEdU+hMurilDYi0sq6TV03g/kJRVQYdat7jgSpUgPHgODfe244GTCE2mHyGnM2k3e0xIvZz+TwX+Bx6eH + NEXT_PUBLIC_TRIGGER_PUBLIC_API_KEY: AgBqHybb2WMXrYm55drkxeNF2Ir1fJnC6cQyk7VsQ6a5MvJSRHxuu4tLMWXvhAvsNmy7f/zEPdKHWtPlMaVmBFma+HydFCdOIif2Zlklso+6Hc6vwup0OohPi50O4cKszJI9NOYoJHygc+VbrawRUFwxxhplkxKTVlxTVC7aaitqS4rkaBT/u12NvNQpABMmP64TFrc6pMNYR71FyDz32sK0P0DkWq/0H5O0ej4TQl8e1cWMJiLJephN7h7Ur4ZsW1BREsmHXToUkVL/ECbo+7KTUrdDpppaI/ttXV6W1Wcn4eZxsAtbARCjIfjTPR4SE8csLsrf9a9ZzruT/SastL1eK0QRS2vcTMeeHrmADSRyfJi5XwCUowJqhpRCuwxeQnALpnqwjcgB4USelaH+5mA+bW28WvlZq9FSgkpWRMjejkRVSKiuSFcF7zFhRW38+kHyLRg/Ge8fH1/yILTabymwrM2+cuf5onrWzbCIXSBTM1nJPtPIOrikQX1u2gdDXQkKxTD2dE5hbhvAPCE+EZMupwU5D91tyq7WdlARuKgKr6ixeBDuReFEC4SX70HMmCnORHD3rqZIhHPfKjwnGCKpskU+DoyMmv2YX0C82NCq+Azf1MM1Ufd8rC0HGOvo3lxon+2az/7haGZj+kcL4uBMsuuhqfvjY5lDReIX8gE9AhiC0PoUXjilW+ZfGmGJjry6A+YsSrDIwQ6fV99kviSocGX90AoQ7nhVcaY= + TRIGGER_API_KEY: AgCuH57uP3NcaOMgiEsR6mU+pN3/VOPoFbDGQsCNW0p5joT3UVP1Z8/upd+wKaUKaSvTwk8K18JQRyQXBqIPJi9r3W0Lk3WeBVkpBUYLzk6ssJocaJdhudcBVwgQatIjsoTQgqSMNyzHdkEkjTCEdAyjN3aXOSNbaVRm9o8udSqOl8uzKC3ue40SBbNlMNG6p4zRE4nH0SHcXeN4La0JqbMzs5yiikm9yvvz8r+CHxhjIAkpC4y9yEIyvHIfUJNqFQKJgQ0geVkTs/FXn3yVQeXn0Akoi8P+oonVHP4loQNVPwuCodzRKGtBXF0vWKe4Tctdk6nVjTR3awUa6v4XwWqf+CHmsBb4m7ZanEZAVT/Vk36tbJjoz3Q0e/RFIol65t1bqzvtGkPVRBQRUDDPdJaW9WWmxeIRyesPWJk5daC8kbCrncZHqkFEaNVSmFcF4crYFZbjvACAx2FLm7q5y/Vdqst+rFor2d7SB5w32hSuuRUjx1uOv2WzsBT2A+nRNlRGHiLmpyeUnuL12+2k8hIR2Au73+Q5JkzE1k5P2jtZ5QS2JOzoBBWF9r2OLG/UXzTHgybptLuOQd4ee96jErh+ue2SrAqILaPlvzGdcTX4cpBnksDvScPh/d2DnIbzPo00jBwsco7v8R1KTdhnb1xP5wlUEgGzWsMfk22cD9ZBYMgPhREx/kn4mLwTwoGnDlg4zH5ejP/OieDcRZwNy8XrMhGigu4ocN5H2hE= + TRIGGER_API_URL: AgCIpCu4Zpo9NeFSTluABhYTvx0TJsXafXneAahiepwFAWKXsmccHc0gxc2qB68V62vLEcq0m9I6bSHuIM8QTq8+dfhQvR58g6hWaHqufvw3f96EiL2sY90keerGqGLsVdw/0vSwpdUstJtKR2+Slt755gUpvGOxb9LmGCHqFN+z1yaT5U6p3EJUhfAUgajU7SCkfEjj6ClL8ASToKCKMeIN9mH00EWs10iGKbYJgINA6IsaVy82q9ti5vvCN5nN6AYdSsfIyOVxNMBubR60yIL19Adt+jPoyF9VP1Nx7kz7HwIaHrwzLylAsRO/F2Tacqtm9wu69XpJmwkKL9GUyNDjC+CbCK/dKuC3kDLM3acPVi9G5aTdAyBz0+69eGBtXjBKaS7OhlL0buKMDpYkSk2pZ7+IeXCc6LuxGp6gplI7e1DpAZ5/mB+ypFuTpzHCgcvcgot+BHkr9nRcgCpQr8FLLLCXqGc8p0jXsNaMy56mO7EFGH6YJ1W7GZRFSdadWBvKP/b/lTBImf8SNGgWEzFuG80/DLlXph2g0ROU/T6qa/BOcKrnKmHYwMHxk2ZC2Trs31NzTb3xNqRBEdNKsFhC5WCAMR3InPkXjeY32hscP5YuA0j2JQRA9c46+FvfKba/69ZPIIuzKBR8/af3FYXq3fzhyI7NqwrCnXL37cyPaehL5VEzxdzzzR+Me4W2oPHBBz64RSPgFjs45Ah26slcOhfJC+zQblJToO26vw== + template: + metadata: + creationTimestamp: null + name: ssr-secret + namespace: public-services + type: Opaque diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 3cdee3f..2a1f6d0 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -48,6 +48,7 @@ jobs: action: deploy namespace: public-services manifests: | + .gitea/kubernetes/sealed-secrets.yaml .gitea/kubernetes/deployment.yaml .gitea/kubernetes/service.yaml .gitea/kubernetes/ingress.yaml diff --git a/config.ts b/config.ts index 8b526a6..5a2711a 100644 --- a/config.ts +++ b/config.ts @@ -1,3 +1,3 @@ export const config = { - siteUrl: "https://ssr.fascinated.cc", + siteUrl: process.env.NEXT_PUBLIC_SITE_URL || "https://ssr.fascinated.cc", }; diff --git a/package.json b/package.json index 0597353..58a5cf8 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev --turbo", + "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" @@ -20,6 +20,9 @@ "@radix-ui/react-toast": "^1.2.1", "@radix-ui/react-tooltip": "^1.1.2", "@tanstack/react-query": "^5.55.4", + "@trigger.dev/nextjs": "^3.0.8", + "@trigger.dev/react": "^3.0.8", + "@trigger.dev/sdk": "^3.0.8", "chart.js": "^4.4.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", @@ -27,8 +30,10 @@ "dexie": "^4.0.8", "dexie-react-hooks": "^1.1.7", "framer-motion": "^11.5.4", + "js-cookie": "^3.0.5", "ky": "^1.7.2", "lucide-react": "^0.446.0", + "mongoose": "^8.7.0", "next": "15.0.0-rc.0", "next-build-id": "^3.0.0", "next-themes": "^0.3.0", @@ -41,6 +46,7 @@ "zod": "^3.23.8" }, "devDependencies": { + "@types/js-cookie": "^3.0.6", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", @@ -49,5 +55,8 @@ "postcss": "^8", "tailwindcss": "^3.4.1", "typescript": "^5" + }, + "trigger.dev": { + "endpointId": "scoresaber-reloaded-KB0Z" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 650c71a..b08050c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,15 @@ importers: '@tanstack/react-query': specifier: ^5.55.4 version: 5.56.2(react@19.0.0-rc-3edc000d-20240926) + '@trigger.dev/nextjs': + specifier: ^3.0.8 + version: 3.0.8(@trigger.dev/sdk@3.0.8)(next@15.0.0-rc.0(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926)) + '@trigger.dev/react': + specifier: ^3.0.8 + version: 3.0.8(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) + '@trigger.dev/sdk': + specifier: ^3.0.8 + version: 3.0.8 chart.js: specifier: ^4.4.4 version: 4.4.4 @@ -62,15 +71,21 @@ importers: framer-motion: specifier: ^11.5.4 version: 11.9.0(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) + js-cookie: + specifier: ^3.0.5 + version: 3.0.5 ky: specifier: ^1.7.2 version: 1.7.2 lucide-react: specifier: ^0.446.0 version: 0.446.0(react@19.0.0-rc-3edc000d-20240926) + mongoose: + specifier: ^8.7.0 + version: 8.7.0 next: specifier: 15.0.0-rc.0 - version: 15.0.0-rc.0(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) + version: 15.0.0-rc.0(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) next-build-id: specifier: ^3.0.0 version: 3.0.0 @@ -99,6 +114,9 @@ importers: specifier: ^3.23.8 version: 3.23.8 devDependencies: + '@types/js-cookie': + specifier: ^3.0.6 + version: 3.0.6 '@types/node': specifier: ^20 version: 20.16.10 @@ -169,6 +187,19 @@ packages: '@formkit/tempo@0.1.2': resolution: {integrity: sha512-jNPPbjL8oj7hK3eHX++CwbR6X4GKQt+x00/q4yeXkwynXHGKL27dylYhpEgwrmediPP4y7s0XtN1if/M/JYujg==} + '@google-cloud/precise-date@4.0.0': + resolution: {integrity: sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==} + engines: {node: '>=14.0.0'} + + '@grpc/grpc-js@1.11.3': + resolution: {integrity: sha512-i9UraDzFHMR+Iz/MhFLljT+fCpgxZ3O6CxwGJ8YuNYHJItIHUzKJpW2LvoFZNnGPwqc9iWy9RAucxV0JoR9aUQ==} + engines: {node: '>=12.10.0'} + + '@grpc/proto-loader@0.7.13': + resolution: {integrity: sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==} + engines: {node: '>=6'} + hasBin: true + '@heroicons/react@2.1.5': resolution: {integrity: sha512-FuzFN+BsHa+7OxbvAERtgBTNeZpUjgM/MIizfVkSCL2/edriN0Hx/DWRCR//aPYwO5QX/YlgLGXk+E3PcfZwjA==} peerDependencies: @@ -319,9 +350,15 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@js-sdsl/ordered-map@4.4.2': + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + '@kurkle/color@0.3.2': resolution: {integrity: sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==} + '@mongodb-js/saslprep@1.1.9': + resolution: {integrity: sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==} + '@next/env@15.0.0-rc.0': resolution: {integrity: sha512-6W0ndQvHR9sXcqcKeR/inD2UTRCs9+VkSK3lfaGmEuZs7EjwwXMO2BPYjz9oBrtfPL3xuTjtXsHKSsalYQ5l1Q==} @@ -398,10 +435,166 @@ packages: resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} engines: {node: '>=12.4.0'} + '@opentelemetry/api-logs@0.52.1': + resolution: {integrity: sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==} + engines: {node: '>=14'} + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/context-async-hooks@1.25.1': + resolution: {integrity: sha512-UW/ge9zjvAEmRWVapOP0qyCvPulWU6cQxGxDbWEFfGOj1VBBZAuOqTo3X6yWmDTD3Xe15ysCZChHncr2xFMIfQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@1.25.1': + resolution: {integrity: sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/exporter-logs-otlp-http@0.52.1': + resolution: {integrity: sha512-qKgywId2DbdowPZpOBXQKp0B8DfhfIArmSic15z13Nk/JAOccBUQdPwDjDnjsM5f0ckZFMVR2t/tijTUAqDZoA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-trace-otlp-grpc@0.52.1': + resolution: {integrity: sha512-pVkSH20crBwMTqB3nIN4jpQKUEoB0Z94drIHpYyEqs7UBr+I0cpYyOR3bqjA/UasQUMROb3GX8ZX4/9cVRqGBQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-trace-otlp-http@0.52.1': + resolution: {integrity: sha512-05HcNizx0BxcFKKnS5rwOV+2GevLTVIRA0tRgWYyw4yCgR53Ic/xk83toYKts7kbzcI+dswInUg/4s8oyA+tqg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-trace-otlp-proto@0.52.1': + resolution: {integrity: sha512-pt6uX0noTQReHXNeEslQv7x311/F1gJzMnp1HD2qgypLRPbXDeMzzeTngRTUaUbP6hqWNtPxuLr4DEoZG+TcEQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-zipkin@1.25.1': + resolution: {integrity: sha512-RmOwSvkimg7ETwJbUOPTMhJm9A9bG1U8s7Zo3ajDh4zM7eYcycQ0dM7FbLD6NXWbI2yj7UY4q8BKinKYBQksyw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/instrumentation@0.52.1': + resolution: {integrity: sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-exporter-base@0.52.1': + resolution: {integrity: sha512-z175NXOtX5ihdlshtYBe5RpGeBoTXVCKPPLiQlD6FHvpM4Ch+p2B0yWKYSrBfLH24H9zjJiBdTrtD+hLlfnXEQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-grpc-exporter-base@0.52.1': + resolution: {integrity: sha512-zo/YrSDmKMjG+vPeA9aBBrsQM9Q/f2zo6N04WMB3yNldJRsgpRBeLLwvAt/Ba7dpehDLOEFBd1i2JCoaFtpCoQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-transformer@0.52.1': + resolution: {integrity: sha512-I88uCZSZZtVa0XniRqQWKbjAUm73I8tpEy/uJYPPYw5d7BRdVk0RfTBQw8kSUl01oVWEuqxLDa802222MYyWHg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/propagator-b3@1.25.1': + resolution: {integrity: sha512-p6HFscpjrv7//kE+7L+3Vn00VEDUJB0n6ZrjkTYHrJ58QZ8B3ajSJhRbCcY6guQ3PDjTbxWklyvIN2ojVbIb1A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/propagator-jaeger@1.25.1': + resolution: {integrity: sha512-nBprRf0+jlgxks78G/xq72PipVK+4or9Ypntw0gVZYNTCSK8rg5SeaGV19tV920CMqBD/9UIOiFr23Li/Q8tiA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/resources@1.25.1': + resolution: {integrity: sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-logs@0.52.1': + resolution: {integrity: sha512-MBYh+WcPPsN8YpRHRmK1Hsca9pVlyyKd4BxOC4SsgHACnl/bPp4Cri9hWhVm5+2tiQ9Zf4qSc1Jshw9tOLGWQA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + + '@opentelemetry/sdk-metrics@1.25.1': + resolution: {integrity: sha512-9Mb7q5ioFL4E4dDrc4wC/A3NTHDat44v4I3p2pLPSxRvqUbDIQyMVr9uK+EU69+HWhlET1VaSrRzwdckWqY15Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-node@0.52.1': + resolution: {integrity: sha512-uEG+gtEr6eKd8CVWeKMhH2olcCHM9dEK68pe0qE0be32BcCRsvYURhHaD1Srngh1SQcnQzZ4TP324euxqtBOJA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@1.25.1': + resolution: {integrity: sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-trace-node@1.25.1': + resolution: {integrity: sha512-nMcjFIKxnFqoez4gUmihdBrbpsEnAX/Xj16sGvZm+guceYE0NE00vLhpDVK6f3q8Q4VFI5xG8JjlXKMB/SkTTQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.25.1': + resolution: {integrity: sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==} + engines: {node: '>=14'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@radix-ui/number@1.1.0': resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==} @@ -690,17 +883,58 @@ packages: '@rushstack/eslint-patch@1.10.4': resolution: {integrity: sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==} + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + '@swc/helpers@0.5.11': resolution: {integrity: sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==} + '@tanstack/query-core@5.0.0-beta.0': + resolution: {integrity: sha512-VGq/H3PuRoj0shOcg1S5Flv3YD2qNz2ttk8w5xe5AHQE1I8NO9EHSBUxezIpk4dD6M7bQDtwHBMqqU2EwMwyUw==} + '@tanstack/query-core@5.56.2': resolution: {integrity: sha512-gor0RI3/R5rVV3gXfddh1MM+hgl0Z4G7tj6Xxpq6p2I03NGPaJ8dITY9Gz05zYYb/EJq9vPas/T4wn9EaDPd4Q==} + '@tanstack/react-query@5.0.0-beta.2': + resolution: {integrity: sha512-JdK1HRw20tuwg3GfT3QZTkuS7s2KDa9FeozuJ7jZULlwPczZagouqYmM6+PL0ad6jfCnw8NzmLFtZdlBx6cTmA==} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + '@tanstack/react-query@5.56.2': resolution: {integrity: sha512-SR0GzHVo6yzhN72pnRhkEFRAHMsUo5ZPzAxfTMvUxFIDVS6W9LYUp6nXW3fcHVdg0ZJl8opSH85jqahvm6DSVg==} peerDependencies: react: ^18 || ^19 + '@trigger.dev/core@3.0.8': + resolution: {integrity: sha512-wmKemzAe+x/sav8ZX6ltpCKCIHLnQmha/YuyT6KooKJ2jDvgSi7rFK/2dn5kF6/XB51NN4/Sh1umWeEPfgjMCg==} + engines: {node: '>=18.20.0'} + + '@trigger.dev/nextjs@3.0.8': + resolution: {integrity: sha512-nT0akL5uLWGcj64dFboYQD/o1DtZpDOyRl2DzfVojaugaItxBwgi/AxLS16059oXNfJY2FTT1wGUgo0vwz1p0Q==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@trigger.dev/sdk': ~2.3.0 || ^3.0.0 + next: '>=12.0.0' + + '@trigger.dev/react@3.0.8': + resolution: {integrity: sha512-tcyFQ/Qp5aW4+5veSl8mIHIuVvFzVO6fr6TOMLYm494NOtiClKhI8BjvCTJwvpv25UOOhSUgB3xrPfDxbbrQ4w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18 + + '@trigger.dev/sdk@3.0.8': + resolution: {integrity: sha512-IwDjNOMgCGP2e4uVarT6EuNyg4D/0sKGsQzQEcT1rNY0ZiSIgL/wVpKMFjDvYuUpyQcI3/EmAr2PMWBDxiOMdg==} + engines: {node: '>=18.20.0'} + + '@types/js-cookie@3.0.6': + resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -722,6 +956,15 @@ packages: '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + '@types/shimmer@1.2.0': + resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} + + '@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==} + '@typescript-eslint/eslint-plugin@7.2.0': resolution: {integrity: sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw==} engines: {node: ^16.0.0 || >=18.0.0} @@ -783,6 +1026,11 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -796,6 +1044,10 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ansi-escapes@5.0.0: + resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==} + engines: {node: '>=12'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -896,6 +1148,10 @@ 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'} + busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -919,6 +1175,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chart.js@4.4.4: resolution: {integrity: sha512-emICKGBABnxhMjUjlYRR12PmOXhJ2eJjEHL2/dZlWjxRAZT1D8xplLFq5M0tMQK8ja+wBS/tuVEJB5C6r7VxJA==} engines: {pnpm: '>=8'} @@ -927,12 +1187,19 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + cjs-module-lexer@1.4.1: + resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} + class-variance-authority@0.7.0: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} engines: {node: '>=6'} @@ -965,6 +1232,14 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + + cronstrue@2.50.0: + resolution: {integrity: sha512-ULYhWIonJzlScCCQrPUG5uMXzXxSixty4djud9SS37DoNxDdkeRocxzHuAo4ImRBUK+mAuU5X9TSwEDccnnuPg==} + hasBin: true + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1065,6 +1340,13 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + engine.io-client@6.5.4: + resolution: {integrity: sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==} + + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + enhanced-resolve@5.17.1: resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} @@ -1103,6 +1385,10 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -1214,6 +1500,13 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + evt@2.5.7: + resolution: {integrity: sha512-dr7Wd16ry5F8WNU1xXLKpFpO3HsoAGg8zC48e08vDdzMzGWCP9/QFGt1PQptEEDh8SwYP3EL8M+d/Gb0kgUp6g==} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -1288,10 +1581,18 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + get-symbol-description@1.0.2: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} @@ -1367,6 +1668,13 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + humanize-duration@3.32.1: + resolution: {integrity: sha512-inh5wue5XdfObhu/IGEMiA1nUXigSGcaKNemcbLRKa7jXYGDZXr3LoT9pTIzq2hPEbld7w/qv9h+ikWGz8fL1g==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1375,6 +1683,9 @@ packages: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} + import-in-the-middle@1.11.1: + resolution: {integrity: sha512-lGdg70ECFGv/OHQXL/IPhcxkFPeQ7YA4zborlA54XHVr58oM50QNxItRiayHMqj1MspC5Y9zaHf+QHod/gq7Ug==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -1486,6 +1797,10 @@ packages: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -1509,6 +1824,10 @@ packages: resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} engines: {node: '>= 0.4'} + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -1529,6 +1848,10 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1553,6 +1876,10 @@ packages: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} + kareem@2.6.3: + resolution: {integrity: sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==} + engines: {node: '>=12.0.0'} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1586,9 +1913,15 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -1601,6 +1934,12 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc + memory-pager@1.5.0: + resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1609,6 +1948,13 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + minimal-polyfills@2.2.3: + resolution: {integrity: sha512-oxdmJ9cL+xV72h0xYxp4tP2d5/fTBpP45H8DIOn9pASuF8a3IYTf+25fMGDYGiWW+MFsuog6KD6nfmhZJQ+uUw==} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -1627,6 +1973,51 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + module-details-from-path@1.0.3: + resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} + + 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 + + mongoose@8.7.0: + resolution: {integrity: sha512-rUCSF1mMYQXjXYdqEQLLlMD3xbcj2j1/hRn+9VnVj7ipzru/UoUZxlj/hWmteKMAh4EFnDZ+BIrmma9l/0Hi1g==} + engines: {node: '>=16.20.1'} + + 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'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1676,6 +2067,10 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1719,6 +2114,10 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1750,6 +2149,10 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -1832,6 +2235,10 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + protobufjs@7.4.0: + resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} + engines: {node: '>=12.0.0'} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1878,6 +2285,14 @@ packages: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-in-the-middle@7.4.0: + resolution: {integrity: sha512-X34iHADNbNDfr6OTStIAHWSAvvKQRYgLO6duASaVf7J2VA3lvmNYboAHOuLC2huav1IwgZJtyEcJCKVzFxOSMQ==} + engines: {node: '>=8.6.0'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1902,6 +2317,9 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + run-exclusive@2.2.19: + resolution: {integrity: sha512-K3mdoAi7tjJ/qT7Flj90L7QyPozwUaAG+CVhkdDje4HLKXUYC3N/Jzkau3flHVDLQVhiHBtcimVodMjN9egYbA==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1945,10 +2363,16 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shimmer@1.2.1: + resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} + side-channel@1.0.6: 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==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -1960,10 +2384,24 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + slug@6.1.0: + resolution: {integrity: sha512-x6vLHCMasg4DR2LPiyFGI0gJJhywY6DTiGhCrOMzb3SOk/0JVLIaL4UhyFSHu04SD3uAavrKY/K3zZ3i6iRcgA==} + + socket.io-client@4.7.5: + resolution: {integrity: sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==} + engines: {node: '>=10.0.0'} + + socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + sparse-bitfield@3.0.3: + resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + stop-iteration-iterator@1.0.0: resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} engines: {node: '>= 0.4'} @@ -2013,6 +2451,10 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -2035,10 +2477,18 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true + superjson@2.2.1: + resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==} + engines: {node: '>=16'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -2060,6 +2510,10 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + terminal-link@3.0.0: + resolution: {integrity: sha512-flFL3m4wuixmf6IfhFJd1YPiLiMuxEc8uHRM1buzIeZPm22Au2pDqBJQgdo7n1WfPU1ONFGv7YDwpFBmHGF6lg==} + engines: {node: '>=12'} + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -2074,6 +2528,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tr46@4.1.1: + resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} + engines: {node: '>=14'} + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -2083,6 +2541,9 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tsafe@1.7.2: + resolution: {integrity: sha512-dAPfQLhCfCRre5qs+Z5Q2a7s2CV7RxffZUmvj7puGaePYjECzWREJFd3w4XSFe/T5tbxgowfItA/JSSZ6Ma3dA==} + tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -2097,6 +2558,10 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} + type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + typed-array-buffer@1.0.2: resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} engines: {node: '>= 0.4'} @@ -2118,6 +2583,10 @@ packages: engines: {node: '>=14.17'} hasBin: true + ulid@2.3.0: + resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==} + hasBin: true + unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} @@ -2130,6 +2599,18 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: 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-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -2165,15 +2646,67 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xmlhttprequest-ssl@2.0.0: + resolution: {integrity: sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==} + engines: {node: '>=0.4.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yaml@2.5.1: resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} engines: {node: '>= 14'} hasBin: true + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zod-error@1.5.0: + resolution: {integrity: sha512-zzopKZ/skI9iXpqCEPj+iLCKl9b88E43ehcU+sbRoHuwGd9F1IDVGQ70TyO6kmfiRL1g4IXkjsXK+g1gLYl4WQ==} + + zod-validation-error@1.5.0: + resolution: {integrity: sha512-/7eFkAI4qV0tcxMBB/3+d2c1P6jzzZYdYSlBuAklzMuCrJu5bzJfHS0yVAS87dRHVlhftd6RFJDIvv03JgkSbw==} + engines: {node: '>=16.0.0'} + peerDependencies: + zod: ^3.18.0 + + zod@3.22.3: + resolution: {integrity: sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==} + zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} @@ -2228,6 +2761,20 @@ snapshots: '@formkit/tempo@0.1.2': {} + '@google-cloud/precise-date@4.0.0': {} + + '@grpc/grpc-js@1.11.3': + dependencies: + '@grpc/proto-loader': 0.7.13 + '@js-sdsl/ordered-map': 4.4.2 + + '@grpc/proto-loader@0.7.13': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.2.3 + protobufjs: 7.4.0 + yargs: 17.7.2 + '@heroicons/react@2.1.5(react@19.0.0-rc-3edc000d-20240926)': dependencies: react: 19.0.0-rc-3edc000d-20240926 @@ -2349,8 +2896,14 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@js-sdsl/ordered-map@4.4.2': {} + '@kurkle/color@0.3.2': {} + '@mongodb-js/saslprep@1.1.9': + dependencies: + sparse-bitfield: 3.0.3 + '@next/env@15.0.0-rc.0': {} '@next/eslint-plugin-next@14.2.13': @@ -2398,9 +2951,197 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} + '@opentelemetry/api-logs@0.52.1': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/api@1.9.0': {} + + '@opentelemetry/context-async-hooks@1.25.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/exporter-logs-otlp-http@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.52.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-trace-otlp-grpc@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@grpc/grpc-js': 1.11.3 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-grpc-exporter-base': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-trace-otlp-http@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-trace-otlp-proto@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-zipkin@1.25.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.11.1 + require-in-the-middle: 7.4.0 + semver: 7.6.3 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/otlp-exporter-base@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/otlp-grpc-exporter-base@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@grpc/grpc-js': 1.11.3 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/otlp-transformer@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + protobufjs: 7.4.0 + + '@opentelemetry/propagator-b3@1.25.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/propagator-jaeger@1.25.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/sdk-logs@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/sdk-metrics@1.25.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + lodash.merge: 4.6.2 + + '@opentelemetry/sdk-node@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-grpc': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-http': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-proto': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-zipkin': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-node': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/sdk-trace-node@1.25.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-b3': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-jaeger': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + semver: 7.6.3 + + '@opentelemetry/semantic-conventions@1.25.1': {} + '@pkgjs/parseargs@0.11.0': optional: true + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + '@radix-ui/number@1.1.0': {} '@radix-ui/primitive@1.1.0': {} @@ -2655,17 +3396,100 @@ snapshots: '@rushstack/eslint-patch@1.10.4': {} + '@socket.io/component-emitter@3.1.2': {} + '@swc/helpers@0.5.11': dependencies: tslib: 2.7.0 + '@tanstack/query-core@5.0.0-beta.0': {} + '@tanstack/query-core@5.56.2': {} + '@tanstack/react-query@5.0.0-beta.2(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926)': + dependencies: + '@tanstack/query-core': 5.0.0-beta.0 + client-only: 0.0.1 + react: 19.0.0-rc-3edc000d-20240926 + optionalDependencies: + react-dom: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) + '@tanstack/react-query@5.56.2(react@19.0.0-rc-3edc000d-20240926)': dependencies: '@tanstack/query-core': 5.56.2 react: 19.0.0-rc-3edc000d-20240926 + '@trigger.dev/core@3.0.8': + dependencies: + '@google-cloud/precise-date': 4.0.0 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/exporter-logs-otlp-http': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-http': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-node': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-node': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + execa: 8.0.1 + humanize-duration: 3.32.1 + socket.io-client: 4.7.5 + superjson: 2.2.1 + zod: 3.22.3 + zod-error: 1.5.0 + zod-validation-error: 1.5.0(zod@3.22.3) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@trigger.dev/nextjs@3.0.8(@trigger.dev/sdk@3.0.8)(next@15.0.0-rc.0(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926))': + dependencies: + '@trigger.dev/sdk': 3.0.8 + debug: 4.3.7 + next: 15.0.0-rc.0(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) + transitivePeerDependencies: + - supports-color + + '@trigger.dev/react@3.0.8(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926)': + dependencies: + '@tanstack/react-query': 5.0.0-beta.2(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926) + '@trigger.dev/core': 3.0.8 + debug: 4.3.7 + react: 19.0.0-rc-3edc000d-20240926 + zod: 3.22.3 + transitivePeerDependencies: + - bufferutil + - react-dom + - react-native + - supports-color + - utf-8-validate + + '@trigger.dev/sdk@3.0.8': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/semantic-conventions': 1.25.1 + '@trigger.dev/core': 3.0.8 + chalk: 5.3.0 + cronstrue: 2.50.0 + debug: 4.3.7 + evt: 2.5.7 + slug: 6.1.0 + terminal-link: 3.0.0 + ulid: 2.3.0 + uuid: 9.0.1 + ws: 8.18.0 + zod: 3.22.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@types/js-cookie@3.0.6': {} + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} @@ -2687,6 +3511,14 @@ snapshots: '@types/semver@7.5.8': {} + '@types/shimmer@1.2.0': {} + + '@types/webidl-conversions@7.0.3': {} + + '@types/whatwg-url@11.0.5': + dependencies: + '@types/webidl-conversions': 7.0.3 + '@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.11.1 @@ -2775,6 +3607,10 @@ snapshots: '@ungap/structured-clone@1.2.0': {} + acorn-import-attributes@1.9.5(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + acorn-jsx@5.3.2(acorn@8.12.1): dependencies: acorn: 8.12.1 @@ -2788,6 +3624,10 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-escapes@5.0.0: + dependencies: + type-fest: 1.4.0 + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -2907,6 +3747,8 @@ snapshots: dependencies: fill-range: 7.1.1 + bson@6.8.0: {} + busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -2930,6 +3772,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.3.0: {} + chart.js@4.4.4: dependencies: '@kurkle/color': 0.3.2 @@ -2946,12 +3790,20 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + cjs-module-lexer@1.4.1: {} + class-variance-authority@0.7.0: dependencies: clsx: 2.0.0 client-only@0.0.1: {} + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + clsx@2.0.0: {} clsx@2.1.1: {} @@ -2980,6 +3832,12 @@ snapshots: concat-map@0.0.1: {} + copy-anything@3.0.5: + dependencies: + is-what: 4.1.16 + + cronstrue@2.50.0: {} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -3086,6 +3944,20 @@ snapshots: emoji-regex@9.2.2: {} + engine.io-client@6.5.4: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + engine.io-parser: 5.2.3 + ws: 8.17.1 + xmlhttprequest-ssl: 2.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + engine.io-parser@5.2.3: {} + enhanced-resolve@5.17.1: dependencies: graceful-fs: 4.2.11 @@ -3195,6 +4067,8 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 + escalade@3.2.0: {} + escape-string-regexp@4.0.0: {} eslint-config-next@14.2.13(eslint@8.57.1)(typescript@5.6.2): @@ -3397,6 +4271,24 @@ snapshots: esutils@2.0.3: {} + evt@2.5.7: + dependencies: + minimal-polyfills: 2.2.3 + run-exclusive: 2.2.19 + tsafe: 1.7.2 + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + fast-deep-equal@3.1.3: {} fast-glob@3.3.2: @@ -3468,6 +4360,8 @@ snapshots: functions-have-names@1.2.3: {} + get-caller-file@2.0.5: {} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 @@ -3476,6 +4370,8 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + get-stream@8.0.1: {} + get-symbol-description@1.0.2: dependencies: call-bind: 1.0.7 @@ -3566,6 +4462,10 @@ snapshots: dependencies: function-bind: 1.1.2 + human-signals@5.0.0: {} + + humanize-duration@3.32.1: {} + ignore@5.3.2: {} import-fresh@3.3.0: @@ -3573,6 +4473,13 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-in-the-middle@1.11.1: + dependencies: + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) + cjs-module-lexer: 1.4.1 + module-details-from-path: 1.0.3 + imurmurhash@0.1.4: {} inflight@1.0.6: @@ -3675,6 +4582,8 @@ snapshots: dependencies: call-bind: 1.0.7 + is-stream@3.0.0: {} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.2 @@ -3698,6 +4607,8 @@ snapshots: call-bind: 1.0.7 get-intrinsic: 1.2.4 + is-what@4.1.16: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -3724,6 +4635,8 @@ snapshots: jiti@1.21.6: {} + js-cookie@3.0.5: {} + js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -3747,6 +4660,8 @@ snapshots: object.assign: 4.1.5 object.values: 1.2.0 + kareem@2.6.3: {} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -3774,8 +4689,12 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.camelcase@4.3.0: {} + lodash.merge@4.6.2: {} + long@5.2.3: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -3786,6 +4705,10 @@ snapshots: dependencies: react: 19.0.0-rc-3edc000d-20240926 + memory-pager@1.5.0: {} + + merge-stream@2.0.0: {} + merge2@1.4.1: {} micromatch@4.0.8: @@ -3793,6 +4716,10 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mimic-fn@4.0.0: {} + + minimal-polyfills@2.2.3: {} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -3809,6 +4736,46 @@ snapshots: minipass@7.1.2: {} + module-details-from-path@1.0.3: {} + + mongodb-connection-string-url@3.0.1: + dependencies: + '@types/whatwg-url': 11.0.5 + whatwg-url: 13.0.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 + + mpath@0.9.0: {} + + mquery@5.0.0: + dependencies: + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + ms@2.1.3: {} mz@2.7.0: @@ -3828,7 +4795,7 @@ snapshots: react: 19.0.0-rc-3edc000d-20240926 react-dom: 19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926) - next@15.0.0-rc.0(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926): + next@15.0.0-rc.0(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-3edc000d-20240926(react@19.0.0-rc-3edc000d-20240926))(react@19.0.0-rc-3edc000d-20240926): dependencies: '@next/env': 15.0.0-rc.0 '@swc/helpers': 0.5.11 @@ -3849,6 +4816,7 @@ snapshots: '@next/swc-win32-arm64-msvc': 15.0.0-rc.0 '@next/swc-win32-ia32-msvc': 15.0.0-rc.0 '@next/swc-win32-x64-msvc': 15.0.0-rc.0 + '@opentelemetry/api': 1.9.0 sharp: 0.33.5 transitivePeerDependencies: - '@babel/core' @@ -3856,6 +4824,10 @@ snapshots: normalize-path@3.0.0: {} + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + object-assign@4.1.1: {} object-hash@3.0.0: {} @@ -3905,6 +4877,10 @@ snapshots: dependencies: wrappy: 1.0.2 + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -3934,6 +4910,8 @@ snapshots: path-key@3.1.1: {} + path-key@4.0.0: {} + path-parse@1.0.7: {} path-scurry@1.11.1: @@ -4004,6 +4982,21 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + protobufjs@7.4.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.16.10 + long: 5.2.3 + punycode@2.3.1: {} queue-microtask@1.2.3: {} @@ -4051,6 +5044,16 @@ snapshots: es-errors: 1.3.0 set-function-name: 2.0.2 + require-directory@2.1.1: {} + + require-in-the-middle@7.4.0: + dependencies: + debug: 4.3.7 + module-details-from-path: 1.0.3 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + resolve-from@4.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -4073,6 +5076,10 @@ snapshots: dependencies: glob: 7.2.3 + run-exclusive@2.2.19: + dependencies: + minimal-polyfills: 2.2.3 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -4145,6 +5152,8 @@ snapshots: shebang-regex@3.0.0: {} + shimmer@1.2.1: {} + side-channel@1.0.6: dependencies: call-bind: 1.0.7 @@ -4152,6 +5161,8 @@ snapshots: get-intrinsic: 1.2.4 object-inspect: 1.13.2 + sift@17.1.3: {} + signal-exit@4.1.0: {} simple-swizzle@0.2.2: @@ -4161,8 +5172,32 @@ snapshots: slash@3.0.0: {} + slug@6.1.0: {} + + socket.io-client@4.7.5: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + engine.io-client: 6.5.4 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-parser@4.2.4: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + source-map-js@1.2.1: {} + sparse-bitfield@3.0.3: + dependencies: + memory-pager: 1.5.0 + stop-iteration-iterator@1.0.0: dependencies: internal-slot: 1.0.7 @@ -4235,6 +5270,8 @@ snapshots: strip-bom@3.0.0: {} + strip-final-newline@3.0.0: {} + strip-json-comments@3.1.1: {} styled-jsx@5.1.3(react@19.0.0-rc-3edc000d-20240926): @@ -4252,10 +5289,19 @@ snapshots: pirates: 4.0.6 ts-interface-checker: 0.1.13 + superjson@2.2.1: + dependencies: + copy-anything: 3.0.5 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + supports-preserve-symlinks-flag@1.0.0: {} tailwind-merge@2.5.2: {} @@ -4293,6 +5339,11 @@ snapshots: tapable@2.2.1: {} + terminal-link@3.0.0: + dependencies: + ansi-escapes: 5.0.0 + supports-hyperlinks: 2.3.0 + text-table@0.2.0: {} thenify-all@1.6.0: @@ -4307,12 +5358,18 @@ snapshots: dependencies: is-number: 7.0.0 + tr46@4.1.1: + dependencies: + punycode: 2.3.1 + ts-api-utils@1.3.0(typescript@5.6.2): dependencies: typescript: 5.6.2 ts-interface-checker@0.1.13: {} + tsafe@1.7.2: {} + tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 @@ -4328,6 +5385,8 @@ snapshots: type-fest@0.20.2: {} + type-fest@1.4.0: {} + typed-array-buffer@1.0.2: dependencies: call-bind: 1.0.7 @@ -4362,6 +5421,8 @@ snapshots: typescript@5.6.2: {} + ulid@2.3.0: {} + unbox-primitive@1.0.2: dependencies: call-bind: 1.0.7 @@ -4377,6 +5438,15 @@ snapshots: util-deprecate@1.0.2: {} + uuid@9.0.1: {} + + webidl-conversions@7.0.0: {} + + whatwg-url@13.0.0: + dependencies: + tr46: 4.1.1 + webidl-conversions: 7.0.0 + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 @@ -4435,8 +5505,38 @@ snapshots: wrappy@1.0.2: {} + ws@8.17.1: {} + + ws@8.18.0: {} + + xmlhttprequest-ssl@2.0.0: {} + + y18n@5.0.8: {} + yaml@2.5.1: {} + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yocto-queue@0.1.0: {} + zod-error@1.5.0: + dependencies: + zod: 3.23.8 + + zod-validation-error@1.5.0(zod@3.22.3): + dependencies: + zod: 3.22.3 + + zod@3.22.3: {} + zod@3.23.8: {} diff --git a/src/app/(pages)/api/player/history/route.ts b/src/app/(pages)/api/player/history/route.ts new file mode 100644 index 0000000..223fbab --- /dev/null +++ b/src/app/(pages)/api/player/history/route.ts @@ -0,0 +1,45 @@ +import { NextRequest, NextResponse } from "next/server"; +import { connectMongo } from "@/common/mongo"; +import { IPlayer, PlayerModel } from "@/common/schema/player-schema"; +import { PlayerHistory } from "@/common/player/player-history"; +import { seedPlayerHistory, sortPlayerHistory } from "@/common/player-utils"; +import { scoresaberService } from "@/common/service/impl/scoresaber"; + +export async function GET(request: NextRequest) { + const playerIdCookie = request.cookies.get("playerId"); + const id = request.nextUrl.searchParams.get("id"); + if (id == null) { + return NextResponse.json( + { error: "Unknown player. Missing: ?id=" }, + { status: 400 }, + ); + } + const shouldCreatePlayer = playerIdCookie?.value === id; + + await connectMongo(); // Connect to Mongo + + // Fetch the player and return their statistic history + let foundPlayer: IPlayer | null = await PlayerModel.findById(id); + if (shouldCreatePlayer && foundPlayer == null) { + foundPlayer = await PlayerModel.create({ + _id: id, + }); + const response = await scoresaberService.lookupPlayer(id, true); + if (response != undefined) { + const { player, rawPlayer } = response; + await seedPlayerHistory(foundPlayer!, player, rawPlayer); + } + } + if (foundPlayer == null) { + return NextResponse.json({ error: "Player not found" }, { status: 404 }); + } + + let history: Map = foundPlayer.getStatisticHistory(); + let fetchedHistory = sortPlayerHistory(history); + fetchedHistory = fetchedHistory.slice(-50); // Get the last 50 entries + const resultHistory: { [key: string]: PlayerHistory } = {}; + for (const [date, history] of fetchedHistory) { + resultHistory[date] = history; + } + return NextResponse.json(resultHistory); +} diff --git a/src/app/(pages)/api/trigger/route.ts b/src/app/(pages)/api/trigger/route.ts new file mode 100644 index 0000000..6331ed9 --- /dev/null +++ b/src/app/(pages)/api/trigger/route.ts @@ -0,0 +1,10 @@ +import { createAppRoute } from "@trigger.dev/nextjs"; +import { client } from "@/trigger"; + +import "@/jobs"; + +//this route is used to send and receive data with Trigger.dev +export const { POST, dynamic } = createAppRoute(client); + +//uncomment this to set a higher max duration (it must be inside your plan limits). Full docs: https://vercel.com/docs/functions/serverless-functions/runtimes#max-duration +//export const maxDuration = 60; diff --git a/src/app/(pages)/page.tsx b/src/app/(pages)/page.tsx index 1e1e403..9a741d9 100644 --- a/src/app/(pages)/page.tsx +++ b/src/app/(pages)/page.tsx @@ -1,18 +1,5 @@ "use client"; -import Card from "@/components/card"; - export default function Home() { - return ( -
-
- -

hello

-
- -

hello

-
-
-
- ); + return
hi
; } diff --git a/src/app/(pages)/player/[...slug]/page.tsx b/src/app/(pages)/player/[...slug]/page.tsx index c7d421c..ce830bb 100644 --- a/src/app/(pages)/player/[...slug]/page.tsx +++ b/src/app/(pages)/player/[...slug]/page.tsx @@ -15,8 +15,8 @@ type Props = { export async function generateMetadata({ params }: Props): Promise { const { slug } = await params; const id = slug[0]; // The players id - const player = await scoresaberService.lookupPlayer(id, false); - if (player === undefined) { + const response = await scoresaberService.lookupPlayer(id, false); + if (response === undefined) { return { title: `Unknown Player`, openGraph: { @@ -24,6 +24,7 @@ export async function generateMetadata({ params }: Props): Promise { }, }; } + const { player } = response; return { title: `${player.name}`, @@ -44,18 +45,18 @@ export default async function Search({ params }: Props) { const id = slug[0]; // The players id const sort: ScoreSort = (slug[1] as ScoreSort) || "recent"; // The sorting method const page = parseInt(slug[2]) || 1; // The page number - const player = await scoresaberService.lookupPlayer(id, false); + const response = await scoresaberService.lookupPlayer(id, false); + if (response == undefined) { + // Invalid player id + return redirect("/"); + } + const scores = await scoresaberService.lookupPlayerScores({ playerId: id, sort, page, }); - - if (player == undefined) { - // Invalid player id - return redirect("/"); - } - + const { player } = response; return (
{ const bio: ScoreSaberBio = { lines: token.bio?.split("\n") || [], linesStripped: token.bio?.replace(/<[^>]+>/g, "")?.split("\n") || [], @@ -66,7 +70,50 @@ export function getScoreSaberPlayerFromToken( description: badge.description, }; }) || []; - const rankHistory = token.histories.split(",").map((rank) => Number(rank)); + + let statisticHistory: { [key: string]: PlayerHistory } = {}; + try { + const history = await ky + .get<{ + [key: string]: PlayerHistory; + }>(`${config.siteUrl}/api/player/history?id=${token.id}`) + .json(); + if (history === undefined || Object.entries(history).length === 0) { + console.log("Player has no history, using fallback"); + throw new Error(); + } + if (history) { + // Use the latest data for today + history[getMidnightAlignedDate(new Date()).toString()] = { + rank: token.rank, + countryRank: token.countryRank, + pp: token.pp, + }; + } + statisticHistory = history; + } catch (error) { + // Fallback to ScoreSaber History if the player has no history + const playerRankHistory = token.histories.split(",").map((value) => { + return parseInt(value); + }); + playerRankHistory.push(token.rank); + + let daysAgo = 0; // Start from current day + for (let i = playerRankHistory.length - 1; i >= 0; i--) { + const rank = playerRankHistory[i]; + const date = getMidnightAlignedDate(getDaysAgoDate(daysAgo)); + daysAgo += 1; // Increment daysAgo for each earlier rank + + statisticHistory[date.toString()] = { + rank: rank, + }; + } + + // Sort the fallback history + statisticHistory = Object.entries(statisticHistory) + .sort() + .reduce((obj, [key, value]) => ({ ...obj, [key]: value }), {}); + } return { id: token.id, @@ -80,7 +127,7 @@ export function getScoreSaberPlayerFromToken( pp: token.pp, role: role, badges: badges, - rankHistory: rankHistory, + statisticHistory: statisticHistory, statistics: token.scoreStats, permissions: token.permissions, banned: token.banned, diff --git a/src/common/mongo.ts b/src/common/mongo.ts new file mode 100644 index 0000000..344a596 --- /dev/null +++ b/src/common/mongo.ts @@ -0,0 +1,12 @@ +import * as mongoose from "mongoose"; + +/** + * Connects to the mongo database + */ +export async function connectMongo() { + const connectionUri = process.env.MONGO_URI; + if (!connectionUri) { + throw new Error("Missing MONGO_URI"); + } + await mongoose.connect(connectionUri); +} diff --git a/src/common/player-utils.ts b/src/common/player-utils.ts new file mode 100644 index 0000000..acd059e --- /dev/null +++ b/src/common/player-utils.ts @@ -0,0 +1,128 @@ +import { PlayerHistory } from "@/common/player/player-history"; +import { IPlayer } from "@/common/schema/player-schema"; +import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token"; +import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player"; +import { getDaysAgoDate, getMidnightAlignedDate } from "@/common/time-utils"; +import { scoresaberService } from "@/common/service/impl/scoresaber"; +import { IO } from "@trigger.dev/sdk"; + +const INACTIVE_CHECK_AGAIN_TIME = 3 * 24 * 60 * 60 * 1000; // 3 days + +/** + * Sorts the player history based on date, + * so the most recent date is first + * + * @param history the player history + */ +export function sortPlayerHistory(history: Map) { + return Array.from(history.entries()).sort( + (a, b) => Date.parse(b[0]) - Date.parse(a[0]), // Sort in descending order + ); +} + +/** + * Sorts the player history based on date, + * so the most recent date is first + * + * @param foundPlayer the player + * @param player the scoresaber player + * @param rawPlayer the raw scoresaber player + */ +export async function seedPlayerHistory( + foundPlayer: IPlayer, + player: ScoreSaberPlayer, + rawPlayer: ScoreSaberPlayerToken, +): Promise> { + // Loop through rankHistory in reverse, from current day backwards + const playerRankHistory = rawPlayer.histories.split(",").map((value) => { + return parseInt(value); + }); + playerRankHistory.push(player.rank); + + let daysAgo = 0; // Start from current day + for (let i = playerRankHistory.length - 1; i >= 0; i--) { + const rank = playerRankHistory[i]; + const date = getMidnightAlignedDate(getDaysAgoDate(daysAgo)); + foundPlayer.setStatisticHistory(date, { + rank: rank, + }); + daysAgo += 1; // Increment daysAgo for each earlier rank + } + + foundPlayer.sortStatisticHistory(); + await foundPlayer.save(); + return foundPlayer.getStatisticHistory(); +} + +/** + * Tracks a players statistics + * + * This is ONLY to be used in Trigger. + * + * @param io the io from Trigger + * @param dateToday the date to use + * @param foundPlayer the player to track + */ +export async function trackScoreSaberPlayer( + dateToday: Date, + foundPlayer: IPlayer, + io?: IO, +) { + io && (await io.logger.info(`Updating statistics for ${foundPlayer.id}...`)); + + // Check if the player is inactive and if we check their inactive status again + if ( + foundPlayer.rawPlayer && + foundPlayer.rawPlayer.inactive && + Date.now() - foundPlayer.getLastTracked().getTime() > + INACTIVE_CHECK_AGAIN_TIME + ) { + io && + (await io.logger.warn( + `Player ${foundPlayer.id} is inactive, skipping...`, + )); + return; + } + + // Lookup player data from the ScoreSaber service + const response = await scoresaberService.lookupPlayer(foundPlayer.id, true); + if (response == undefined) { + io && + (await io.logger.warn( + `Player ${foundPlayer.id} not found on ScoreSaber`, + )); + return; + } + const { player, rawPlayer } = response; + foundPlayer.rawPlayer = player; // Update the raw player data + + if (player.inactive) { + io && (await io.logger.warn(`Player ${foundPlayer.id} is inactive`)); + await foundPlayer.save(); // Save the player + return; + } + + const statisticHistory = foundPlayer.getStatisticHistory(); + + // Seed the history with ScoreSaber data if no history exists + if (statisticHistory.size === 0) { + io && (await io.logger.info(`Seeding history for ${foundPlayer.id}...`)); + await seedPlayerHistory(foundPlayer, player, rawPlayer); + io && (await io.logger.info(`Seeded history for ${foundPlayer.id}`)); + } + + // Update current day's statistics + let history = foundPlayer.getHistory(dateToday); + if (history == undefined) { + history = {}; // Initialize if history is not found + } + // Set the history data + history.pp = player.pp; + history.countryRank = player.countryRank; + history.rank = player.rank; + foundPlayer.setStatisticHistory(dateToday, history); + foundPlayer.sortStatisticHistory(); + await foundPlayer.save(); + + io && (await io.logger.info(`Updated statistics for ${foundPlayer.id}`)); +} diff --git a/src/common/player/player-history.ts b/src/common/player/player-history.ts new file mode 100644 index 0000000..1f7dd81 --- /dev/null +++ b/src/common/player/player-history.ts @@ -0,0 +1,16 @@ +export interface PlayerHistory { + /** + * The player's rank. + */ + rank?: number; + + /** + * The player's country rank. + */ + countryRank?: number; + + /** + * The pp of the player. + */ + pp?: number; +} diff --git a/src/common/schema/player-schema.ts b/src/common/schema/player-schema.ts new file mode 100644 index 0000000..4835229 --- /dev/null +++ b/src/common/schema/player-schema.ts @@ -0,0 +1,123 @@ +import mongoose, { Document, Schema } from "mongoose"; +import { PlayerHistory } from "@/common/player/player-history"; +import { getMidnightAlignedDate } from "@/common/time-utils"; +import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player"; + +// Interface for Player Document +export interface IPlayer extends Document { + /** + * The player's id + */ + id: string; + + /** + * The player's statistic history + */ + statisticHistory: Map; + + /** + * The last time the player was tracked + */ + lastTracked: Date; + + /** + * The raw player data. + */ + rawPlayer: ScoreSaberPlayer; + + /** + * Gets when this player was last tracked. + */ + getLastTracked(): Date; + + /** + * Gets the history for the given date + * + * @param date + */ + getHistory(date: Date): PlayerHistory; + + /** + * Gets all the statistic history + */ + getStatisticHistory(): Map; + + /** + * Sets the statistic history for the given date + * + * @param date the date to set it on + * @param data the data to set + */ + setStatisticHistory(date: Date, data: PlayerHistory): void; + + /** + * Sorts the statistic history + */ + sortStatisticHistory(): Map; +} + +// Mongoose Schema definition for Player +const PlayerSchema = new Schema({ + _id: { type: String, required: true }, + lastTracked: { type: Date, default: new Date(), required: false }, + rawPlayer: { type: Object, required: false }, + statisticHistory: { type: Map, default: () => new Map(), required: false }, +}); + +PlayerSchema.methods.getLastTracked = function (): Date { + return this.lastTracked || new Date(); +}; + +PlayerSchema.methods.getHistory = function (date: Date): PlayerHistory { + return ( + this.statisticHistory.get(getMidnightAlignedDate(date).toString()) || {} + ); +}; + +PlayerSchema.methods.getStatisticHistory = function (): Map< + Date, + PlayerHistory +> { + if (!this.statisticHistory) { + this.statisticHistory = new Map(); + } + return this.statisticHistory; +}; + +PlayerSchema.methods.setStatisticHistory = function ( + date: Date, + data: PlayerHistory, +): void { + if (!this.statisticHistory) { + this.statisticHistory = new Map(); + } + const alignedDate = getMidnightAlignedDate(date).toString(); + return this.statisticHistory.set(alignedDate, data); +}; + +PlayerSchema.methods.sortStatisticHistory = function (): Map< + Date, + PlayerHistory +> { + if (!this.statisticHistory) { + this.statisticHistory = new Map(); + } + + // Sort the player's history + this.statisticHistory = new Map( + Array.from(this.statisticHistory.entries() as [string, PlayerHistory][]) + .sort( + (a: [string, PlayerHistory], b: [string, PlayerHistory]) => + Date.parse(b[0]) - Date.parse(a[0]), + ) + // Convert the date strings back to Date objects for the resulting Map + .map(([date, history]) => [new Date(date).toString(), history]), + ); + return this.statisticHistory; +}; + +// Mongoose Model for Player +const PlayerModel = + mongoose.models.Player || mongoose.model("Player", PlayerSchema); + +export { PlayerModel }; diff --git a/src/common/service/impl/scoresaber.ts b/src/common/service/impl/scoresaber.ts index b83e07d..5f8831b 100644 --- a/src/common/service/impl/scoresaber.ts +++ b/src/common/service/impl/scoresaber.ts @@ -62,7 +62,13 @@ class ScoreSaberService extends Service { async lookupPlayer( playerId: string, useProxy = true, - ): Promise { + ): Promise< + | { + player: ScoreSaberPlayer; + rawPlayer: ScoreSaberPlayerToken; + } + | undefined + > { const before = performance.now(); this.log(`Looking up player "${playerId}"...`); const token = await this.fetch( @@ -75,7 +81,10 @@ class ScoreSaberService extends Service { this.log( `Found player "${playerId}" in ${(performance.now() - before).toFixed(0)}ms`, ); - return getScoreSaberPlayerFromToken(token); + return { + player: await getScoreSaberPlayerFromToken(token), + rawPlayer: token, + }; } /** diff --git a/src/common/time-utils.ts b/src/common/time-utils.ts index 28203fc..90c46a2 100644 --- a/src/common/time-utils.ts +++ b/src/common/time-utils.ts @@ -27,3 +27,45 @@ export function timeAgo(input: Date | number) { } } } + +/** + * Gets the midnight aligned date + * + * @param date the date + */ +export function getMidnightAlignedDate(date: Date) { + return new Date(date.getFullYear(), date.getMonth(), date.getDate()); +} + +/** + * Gets the date X days ago + * + * @param days the number of days to go back + * @returns {Date} A Date object representing the date X days ago + */ +export function getDaysAgoDate(days: number): Date { + const date = new Date(); + date.setDate(date.getDate() - days); + return date; +} + +/** + * Gets the amount of days ago a date was + * + * @param date the date + * @returns the amount of days + */ +export function getDaysAgo(date: Date): number { + const now = new Date(); + const diffTime = Math.abs(now.getTime() - date.getTime()); + return Math.ceil(diffTime / (1000 * 60 * 60 * 24)) - 1; +} + +/** + * Parses a date from a string + * + * @param date the date + */ +export function parseDate(date: string): Date { + return new Date(date); +} diff --git a/src/common/website-utils.ts b/src/common/website-utils.ts index ae1369c..54020b6 100644 --- a/src/common/website-utils.ts +++ b/src/common/website-utils.ts @@ -1,10 +1,12 @@ +import Cookies from "js-cookie"; + /** * Sets the player id cookie * * @param playerId the player id to set */ export function setPlayerIdCookie(playerId: string) { - document.cookie = `playerId=${playerId}`; + Cookies.set("playerId", playerId, { path: "/" }); } /** diff --git a/src/components/player/player-data.tsx b/src/components/player/player-data.tsx index 584e4e5..da0eae8 100644 --- a/src/components/player/player-data.tsx +++ b/src/components/player/player-data.tsx @@ -35,7 +35,7 @@ export default function PlayerData({ }); if (data && (!isLoading || !isError)) { - player = data; + player = data.player; } return ( @@ -55,7 +55,7 @@ export default function PlayerData({ page={page} /> -