From edb7146d6d8c5914b0362d74c08b2cd03583377c Mon Sep 17 00:00:00 2001 From: Ralex <95540504+Ralex91@users.noreply.github.com> Date: Thu, 16 Oct 2025 23:12:40 +0200 Subject: [PATCH 01/17] refactor: add typescript & pnpm workspace & docker file --- .dockerignore | 3 + .env.example | 2 + .gitignore | 37 +- .vscode/extensions.json | 2 + Dockerfile | 66 + config.mjs | 103 - config/game.json | 4 + config/quizz/example.json | 28 + jsconfig.json | 7 - next.config.mjs | 16 - package-lock.json | 6851 ----------------- package.json | 37 +- packages/common/.gitignore | 1 + packages/common/package.json | 13 + packages/common/src/types/game/index.ts | 30 + packages/common/src/types/game/socket.ts | 72 + packages/common/src/types/game/status.ts | 58 + packages/common/tsconfig.json | 10 + packages/socket/.gitignore | 2 + packages/socket/esbuild.config.js | 19 + packages/socket/package.json | 24 + packages/socket/src/env.ts | 14 + packages/socket/src/index.ts | 159 + packages/socket/src/services/config.ts | 110 + packages/socket/src/services/game.ts | 384 + .../socket/src/utils/inviteCode.ts | 4 +- packages/socket/src/utils/sleep.ts | 4 + packages/socket/src/utils/validator.ts | 8 + packages/socket/tsconfig.json | 11 + packages/web/.gitignore | 42 + .../web/.prettierrc.json | 0 packages/web/README.md | 36 + .../web/eslint.config.mjs | 7 +- packages/web/next.config.mjs | 10 + packages/web/package.json | 45 + packages/web/postcss.config.mjs | 5 + {public => packages/web/public}/icon.svg | 0 .../web/public}/sounds/answersMusic.mp3 | Bin .../web/public}/sounds/answersSound.mp3 | Bin .../web/public}/sounds/boump.mp3 | Bin .../web/public}/sounds/first.mp3 | Bin .../web/public}/sounds/results.mp3 | Bin .../web/public}/sounds/second.mp3 | Bin .../web/public}/sounds/show.mp3 | Bin .../web/public}/sounds/snearRoll.mp3 | Bin .../web/public}/sounds/three.mp3 | Bin packages/web/src/app/(auth)/layout.tsx | 17 + packages/web/src/app/(auth)/manager/page.tsx | 43 + packages/web/src/app/(auth)/page.tsx | 38 + packages/web/src/app/game/[gameId]/page.tsx | 78 + packages/web/src/app/game/layout.tsx | 17 + .../src/app/game/manager/[gameId]/page.tsx | 112 + .../web/src/app}/globals.css | 9 +- packages/web/src/app/layout.tsx | 29 + packages/web/src/app/socket/route.ts | 10 + .../web/src}/assets/background.webp | Bin {src => packages/web/src}/assets/loader.svg | 0 {src => packages/web/src}/assets/logo.svg | 0 .../web/src/components/AnswerButton.tsx | 8 +- .../web/src/components/Button.tsx | 6 +- .../web/src/components/Form.tsx | 4 +- packages/web/src/components/Input.tsx | 21 + .../web/src/components/Loader.tsx | 2 +- .../web/src/components/Toaster.tsx | 4 +- .../web/src/components/game/GameWrapper.tsx | 87 + .../game/create/ManagerPassword.tsx | 52 + .../components/game/create/SelectQuizz.tsx | 79 + .../web/src/components/game/join/Room.tsx | 37 + .../web/src/components/game/join/Username.tsx | 44 + .../src/components/game/states/Answers.tsx | 114 + .../components/game/states/Leaderboard.tsx | 10 +- .../web/src/components/game/states/Podium.tsx | 36 +- .../src/components/game/states/Prepared.tsx | 11 +- .../src/components/game/states/Question.tsx | 15 +- .../src/components/game/states/Responses.tsx | 125 + .../web/src/components/game/states/Result.tsx | 26 +- .../web/src/components/game/states/Room.tsx | 70 + .../web/src/components/game/states/Start.tsx | 41 +- .../web/src/components/game/states/Wait.tsx | 9 +- .../web/src/components/icons/Circle.tsx | 7 +- .../web/src/components/icons/CricleCheck.tsx | 8 +- .../web/src/components/icons/CricleXmark.tsx | 8 +- .../web/src/components/icons/Pentagon.tsx | 8 +- .../web/src/components/icons/Rhombus.tsx | 7 +- .../web/src/components/icons/Square.tsx | 7 +- .../web/src/components/icons/Triangle.tsx | 7 +- packages/web/src/contexts/socketProvider.tsx | 140 + packages/web/src/env.ts | 14 + .../web/src/hook/useScreenSize.ts | 0 packages/web/src/stores/game.tsx | 44 + packages/web/src/stores/player.tsx | 37 + packages/web/src/utils/constants.ts | 63 + packages/web/tsconfig.json | 31 + pnpm-lock.yaml | 4911 ++++++++++++ pnpm-workspace.yaml | 2 + postcss.config.js | 6 - socket/index.js | 74 - socket/package.json | 3 - socket/roles/manager.js | 123 - socket/roles/player.js | 104 - socket/utils/convertTimeToPoint.js | 13 - socket/utils/cooldown.js | 30 - socket/utils/deepClone.js | 20 - socket/utils/round.js | 114 - socket/validator.js | 12 - src/components/Input.jsx | 13 - src/components/ManagerPassword.jsx | 53 - src/components/game/GameWrapper.jsx | 77 - src/components/game/join/Room.jsx | 42 - src/components/game/join/Username.jsx | 50 - src/components/game/states/Answers.jsx | 189 - src/components/game/states/Room.jsx | 65 - src/constants.js | 61 - src/context/player.jsx | 55 - src/context/socket.jsx | 19 - src/pages/_app.js | 33 - src/pages/_document.js | 13 - src/pages/game.jsx | 58 - src/pages/index.js | 36 - src/pages/manager.jsx | 95 - tailwind.config.js | 25 - tsconfig.json | 15 + 122 files changed, 7568 insertions(+), 8502 deletions(-) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 Dockerfile delete mode 100644 config.mjs create mode 100644 config/game.json create mode 100644 config/quizz/example.json delete mode 100644 jsconfig.json delete mode 100644 next.config.mjs delete mode 100644 package-lock.json create mode 100644 packages/common/.gitignore create mode 100644 packages/common/package.json create mode 100644 packages/common/src/types/game/index.ts create mode 100644 packages/common/src/types/game/socket.ts create mode 100644 packages/common/src/types/game/status.ts create mode 100644 packages/common/tsconfig.json create mode 100644 packages/socket/.gitignore create mode 100644 packages/socket/esbuild.config.js create mode 100644 packages/socket/package.json create mode 100644 packages/socket/src/env.ts create mode 100644 packages/socket/src/index.ts create mode 100644 packages/socket/src/services/config.ts create mode 100644 packages/socket/src/services/game.ts rename socket/utils/generateRoomId.js => packages/socket/src/utils/inviteCode.ts (78%) create mode 100644 packages/socket/src/utils/sleep.ts create mode 100644 packages/socket/src/utils/validator.ts create mode 100644 packages/socket/tsconfig.json create mode 100644 packages/web/.gitignore rename .prettierrc.json => packages/web/.prettierrc.json (100%) create mode 100644 packages/web/README.md rename eslint.config.mjs => packages/web/eslint.config.mjs (96%) create mode 100644 packages/web/next.config.mjs create mode 100644 packages/web/package.json create mode 100644 packages/web/postcss.config.mjs rename {public => packages/web/public}/icon.svg (100%) rename {public => packages/web/public}/sounds/answersMusic.mp3 (100%) rename {public => packages/web/public}/sounds/answersSound.mp3 (100%) rename {public => packages/web/public}/sounds/boump.mp3 (100%) rename {public => packages/web/public}/sounds/first.mp3 (100%) rename {public => packages/web/public}/sounds/results.mp3 (100%) rename {public => packages/web/public}/sounds/second.mp3 (100%) rename {public => packages/web/public}/sounds/show.mp3 (100%) rename {public => packages/web/public}/sounds/snearRoll.mp3 (100%) rename {public => packages/web/public}/sounds/three.mp3 (100%) create mode 100644 packages/web/src/app/(auth)/layout.tsx create mode 100644 packages/web/src/app/(auth)/manager/page.tsx create mode 100644 packages/web/src/app/(auth)/page.tsx create mode 100644 packages/web/src/app/game/[gameId]/page.tsx create mode 100644 packages/web/src/app/game/layout.tsx create mode 100644 packages/web/src/app/game/manager/[gameId]/page.tsx rename {src/styles => packages/web/src/app}/globals.css (96%) create mode 100644 packages/web/src/app/layout.tsx create mode 100644 packages/web/src/app/socket/route.ts rename {src => packages/web/src}/assets/background.webp (100%) rename {src => packages/web/src}/assets/loader.svg (100%) rename {src => packages/web/src}/assets/logo.svg (100%) rename src/components/AnswerButton.jsx => packages/web/src/components/AnswerButton.tsx (67%) rename src/components/Button.jsx => packages/web/src/components/Button.tsx (54%) rename src/components/Form.jsx => packages/web/src/components/Form.tsx (57%) create mode 100644 packages/web/src/components/Input.tsx rename src/components/Loader.jsx => packages/web/src/components/Loader.tsx (69%) rename src/components/Toaster.jsx => packages/web/src/components/Toaster.tsx (84%) create mode 100644 packages/web/src/components/game/GameWrapper.tsx create mode 100644 packages/web/src/components/game/create/ManagerPassword.tsx create mode 100644 packages/web/src/components/game/create/SelectQuizz.tsx create mode 100644 packages/web/src/components/game/join/Room.tsx create mode 100644 packages/web/src/components/game/join/Username.tsx create mode 100644 packages/web/src/components/game/states/Answers.tsx rename src/components/game/states/Leaderboard.jsx => packages/web/src/components/game/states/Leaderboard.tsx (64%) rename src/components/game/states/Podium.jsx => packages/web/src/components/game/states/Podium.tsx (76%) rename src/components/game/states/Prepared.jsx => packages/web/src/components/game/states/Prepared.tsx (75%) rename src/components/game/states/Question.jsx => packages/web/src/components/game/states/Question.tsx (68%) create mode 100644 packages/web/src/components/game/states/Responses.tsx rename src/components/game/states/Result.jsx => packages/web/src/components/game/states/Result.tsx (64%) create mode 100644 packages/web/src/components/game/states/Room.tsx rename src/components/game/states/Start.jsx => packages/web/src/components/game/states/Start.tsx (59%) rename src/components/game/states/Wait.jsx => packages/web/src/components/game/states/Wait.tsx (55%) rename src/components/icons/Circle.jsx => packages/web/src/components/icons/Circle.tsx (86%) rename src/components/icons/CricleCheck.jsx => packages/web/src/components/icons/CricleCheck.tsx (91%) rename src/components/icons/CricleXmark.jsx => packages/web/src/components/icons/CricleXmark.tsx (92%) rename src/components/icons/Pentagon.jsx => packages/web/src/components/icons/Pentagon.tsx (89%) rename src/components/icons/Rhombus.jsx => packages/web/src/components/icons/Rhombus.tsx (74%) rename src/components/icons/Square.jsx => packages/web/src/components/icons/Square.tsx (62%) rename src/components/icons/Triangle.jsx => packages/web/src/components/icons/Triangle.tsx (63%) create mode 100644 packages/web/src/contexts/socketProvider.tsx create mode 100644 packages/web/src/env.ts rename src/hook/useScreenSize.js => packages/web/src/hook/useScreenSize.ts (100%) create mode 100644 packages/web/src/stores/game.tsx create mode 100644 packages/web/src/stores/player.tsx create mode 100644 packages/web/src/utils/constants.ts create mode 100644 packages/web/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml delete mode 100644 postcss.config.js delete mode 100644 socket/index.js delete mode 100644 socket/package.json delete mode 100644 socket/roles/manager.js delete mode 100644 socket/roles/player.js delete mode 100644 socket/utils/convertTimeToPoint.js delete mode 100644 socket/utils/cooldown.js delete mode 100644 socket/utils/deepClone.js delete mode 100644 socket/utils/round.js delete mode 100644 socket/validator.js delete mode 100644 src/components/Input.jsx delete mode 100644 src/components/ManagerPassword.jsx delete mode 100644 src/components/game/GameWrapper.jsx delete mode 100644 src/components/game/join/Room.jsx delete mode 100644 src/components/game/join/Username.jsx delete mode 100644 src/components/game/states/Answers.jsx delete mode 100644 src/components/game/states/Room.jsx delete mode 100644 src/constants.js delete mode 100644 src/context/player.jsx delete mode 100644 src/context/socket.jsx delete mode 100644 src/pages/_app.js delete mode 100644 src/pages/_document.js delete mode 100644 src/pages/game.jsx delete mode 100644 src/pages/index.js delete mode 100644 src/pages/manager.jsx delete mode 100644 tailwind.config.js create mode 100644 tsconfig.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ca62534 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +node_modules +.pnpm-store +.git diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..dc87529 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +SOCKET_URL=http://localhost:3001 # Default: http://localhost:3001 +SOCKER_PORT=3001 # Default: 3001 diff --git a/.gitignore b/.gitignore index 7425c08..7af7f04 100644 --- a/.gitignore +++ b/.gitignore @@ -1,37 +1,2 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies /node_modules -/socket/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts +.env \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index c4e1787..efb5d6f 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,8 @@ "recommendations": [ "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", + "usernamehw.errorlens", + "YoavBls.pretty-ts-errors", "bradlc.vscode-tailwindcss", "meganrogge.template-string-converter", "vincaslt.highlight-matching-tag", diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..974acca --- /dev/null +++ b/Dockerfile @@ -0,0 +1,66 @@ +FROM node:24-alpine AS base + +# Enable and prepare pnpm via Corepack +RUN corepack enable && corepack prepare pnpm@latest --activate + +# ----- DEPENDENCIES ----- +FROM base AS deps +WORKDIR /app + +# Copy pnpm configuration files +COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./ +COPY packages/web/package.json ./packages/web/ +COPY packages/socket/package.json ./packages/socket/ + +# Install only production dependencies +RUN pnpm install --frozen-lockfile --prod + +# ----- BUILDER ----- +FROM base AS builder +WORKDIR /app + +# Copy all monorepo files +COPY . . + +# Install all dependencies (including dev) for build +RUN pnpm install --frozen-lockfile + +# Build Next.js app with standalone output for smaller runtime image +WORKDIR /app/packages/web +RUN pnpm build + +# Build socket server if needed (TypeScript or similar) +WORKDIR /app/packages/socket +RUN if [ -f "tsconfig.json" ]; then pnpm build; fi + +# ----- RUNNER ----- +FROM node:24-alpine AS runner +WORKDIR /app + +# Create a non-root user for better security +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nodejs + + +# Enable pnpm in the runtime image +RUN corepack enable && corepack prepare pnpm@latest --activate + +# Copy configuration files +COPY pnpm-workspace.yaml package.json ./ + +# Copy the Next.js standalone build +COPY --from=builder /app/packages/web/.next/standalone ./ +COPY --from=builder /app/packages/web/.next/static ./packages/web/.next/static +COPY --from=builder /app/packages/web/public ./packages/web/public + +# Copy the socket server build +COPY --from=builder /app/packages/socket/dist ./packages/socket/dist + +# Expose the web and socket ports +EXPOSE 3000 5505 + +# Environment variables +ENV NODE_ENV=production + +# Start both services (Next.js web app + Socket server) +CMD ["sh", "-c", "node packages/web/server.js & node packages/socket/dist/index.cjs"] diff --git a/config.mjs b/config.mjs deleted file mode 100644 index 37c6fb6..0000000 --- a/config.mjs +++ /dev/null @@ -1,103 +0,0 @@ -export const WEBSOCKET_PUBLIC_URL = "http://localhost:5505/" -export const WEBSOCKET_SERVER_PORT = 5505 - -const QUIZZ_CONFIG = { - password: "PASSWORD", - subject: "Adobe", - questions: [ - { - question: "Who are the founders of Adobe?", - answers: [ - "Steve Jobs and Charles Geschke", - "Jhon Warnock and Charles Geschke", - "Jhon Jonse and Charles Geskie", - "Bill Gate", - ], - solution: 1, - cooldown: 5, - time: 15, - }, - { - question: "What is Adobe's most famous software?", - answers: ["Encore", "AfterEffect", "Creative Cloud", "Photoshop"], - image: - "https://images.unsplash.com/photo-1626785774573-4b799315345d?q=80&w=500&auto=webp", - solution: 3, - cooldown: 5, - time: 15, - }, - { - question: "When was Adobe created?", - answers: ["2000", "1982", "2003", "1987"], - solution: 1, - cooldown: 5, - time: 15, - }, - { - question: "Where is headquertes located?", - answers: [ - "San Jose, California", - "Bookworm, Cascui", - "DowTown, Texas", - "Tokyo, Japan", - ], - solution: 0, - cooldown: 5, - time: 15, - }, - { - question: "How many employees at Adobe?", - answers: [ - "15,423 employees", - "30,803 employees", - "25,988 employees", - "5,073 employees", - ], - image: - "https://images.unsplash.com/photo-1504384308090-c894fdcc538d?q=80&w=500&auto=webp", - solution: 2, - cooldown: 5, - time: 15, - }, - { - question: "Who is the Current CEO?", - answers: [ - "Jhon Warnock", - "Victor Newway", - "Mark Java", - "Shantanu Narayen", - ], - image: - "https://images.unsplash.com/photo-1435348773030-a1d74f568bc2?q=80&w=500&auto=webp", - solution: 3, - cooldown: 5, - time: 15, - }, - { - question: "Adobe's core business is focused on?", - answers: [ - "Creative Software", - "Video Game", - "Logistics software", - "Other", - ], - image: - "https://images.unsplash.com/photo-1582736317407-371893d9e146?q=80&w=500&auto=webp", - solution: 0, - cooldown: 5, - time: 15, - }, - ], -} - -// DONT CHANGE -export const GAME_STATE_INIT = { - started: false, - players: [], - playersAnswer: [], - manager: null, - room: null, - currentQuestion: 0, - roundStartTime: 0, - ...QUIZZ_CONFIG, -} diff --git a/config/game.json b/config/game.json new file mode 100644 index 0000000..0b4f9eb --- /dev/null +++ b/config/game.json @@ -0,0 +1,4 @@ +{ + "managerPassword": "PASSWORD", + "music": true +} diff --git a/config/quizz/example.json b/config/quizz/example.json new file mode 100644 index 0000000..f49a60a --- /dev/null +++ b/config/quizz/example.json @@ -0,0 +1,28 @@ +{ + "subject": "Example Quizz", + "questions": [ + { + "question": "What is good answer ?", + "answers": ["No", "Good answer", "No", "No"], + "solution": 1, + "cooldown": 5, + "time": 15 + }, + { + "question": "What is good answer with image ?", + "answers": ["No", "No", "No", "Good answer"], + "image": "https://placehold.co/600x400.png", + "solution": 3, + "cooldown": 5, + "time": 20 + }, + { + "question": "What is good answer with two answers ?", + "answers": ["Good answer", "No"], + "image": "https://placehold.co/600x400.png", + "solution": 0, + "cooldown": 5, + "time": 20 + } + ] +} diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index fedeac1..0000000 --- a/jsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "compilerOptions": { - "paths": { - "@/*": ["./src/*"], - }, - }, -} diff --git a/next.config.mjs b/next.config.mjs deleted file mode 100644 index 395dd18..0000000 --- a/next.config.mjs +++ /dev/null @@ -1,16 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - reactStrictMode: true, - images: { - remotePatterns: [ - { - protocol: "https", - hostname: "images.unsplash.com", - port: "", - pathname: "/**", - }, - ], - }, -} - -export default nextConfig diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index d092cce..0000000 --- a/package-lock.json +++ /dev/null @@ -1,6851 +0,0 @@ -{ - "name": "rahoot", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "rahoot", - "version": "0.1.0", - "dependencies": { - "clsx": "^2.1.0", - "concurrently": "^8.2.2", - "next": "^14.2.32", - "react": "^18", - "react-confetti": "^6.1.0", - "react-dom": "^18", - "react-hot-toast": "^2.4.1", - "socket.io": "^4.7.4", - "socket.io-client": "^4.7.4", - "use-sound": "^4.0.1", - "yup": "^1.3.3" - }, - "devDependencies": { - "autoprefixer": "^10.0.1", - "eslint": "^9.36.0", - "eslint-config-next": "^15.5.4", - "postcss": "^8", - "prettier-plugin-tailwindcss": "^0.5.14", - "tailwindcss": "^3.3.0" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@emnapi/core": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz", - "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", - "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", - "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.15.2", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@next/env": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.33.tgz", - "integrity": "sha512-CgVHNZ1fRIlxkLhIX22flAZI/HmpDaZ8vwyJ/B0SDPTBuLZ1PJ+DWMjCHhqnExfmSQzA/PbZi8OAc7PAq2w9IA==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.4.tgz", - "integrity": "sha512-SR1vhXNNg16T4zffhJ4TS7Xn7eq4NfKfcOsRwea7RIAHrjRpI9ALYbamqIJqkAhowLlERffiwk0FMvTLNdnVtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-glob": "3.3.1" - } - }, - "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz", - "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz", - "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz", - "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz", - "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz", - "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz", - "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz", - "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz", - "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz", - "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.4.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", - "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", - "license": "MIT" - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "license": "Apache-2.0" - }, - "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", - "license": "Apache-2.0", - "dependencies": { - "@swc/counter": "^0.1.3", - "tslib": "^2.4.0" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "24.5.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz", - "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.12.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.1.tgz", - "integrity": "sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/type-utils": "8.44.1", - "@typescript-eslint/utils": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.44.1", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.44.1.tgz", - "integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.1.tgz", - "integrity": "sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.44.1", - "@typescript-eslint/types": "^8.44.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz", - "integrity": "sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz", - "integrity": "sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.44.1.tgz", - "integrity": "sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/utils": "8.44.1", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.1.tgz", - "integrity": "sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz", - "integrity": "sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.44.1", - "@typescript-eslint/tsconfig-utils": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.1.tgz", - "integrity": "sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz", - "integrity": "sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.44.1", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", - "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", - "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", - "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", - "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.0", - "es-object-atoms": "^1.1.1", - "get-intrinsic": "^1.3.0", - "is-string": "^1.1.1", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", - "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-shim-unscopables": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.10.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", - "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", - "dev": true, - "license": "MPL-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "license": "MIT", - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.8.tgz", - "integrity": "sha512-be0PUaPsQX/gPWWgFsdD+GFzaoig5PXaUC1xLkQiYdDnANU8sMnHoQd8JhbJQuvTWrWLyeFN9Imb5Qtfvr4RrQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.26.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", - "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.8.3", - "caniuse-lite": "^1.0.30001741", - "electron-to-chromium": "^1.5.218", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001745", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001745.tgz", - "integrity": "sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "license": "MIT" - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/concurrently": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", - "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "date-fns": "^2.30.0", - "lodash": "^4.17.21", - "rxjs": "^7.8.1", - "shell-quote": "^1.8.1", - "spawn-command": "0.0.2", - "supports-color": "^8.1.1", - "tree-kill": "^1.2.2", - "yargs": "^17.7.2" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": "^14.13.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, - "license": "MIT" - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.227", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.227.tgz", - "integrity": "sha512-ITxuoPfJu3lsNWUi2lBM2PaBPYgH3uqmxut5vmBxgYvyI4AlJ6P3Cai1O76mOrkJCBzq0IxWg/NtqOrpu/0gKA==", - "dev": true, - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/engine.io": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", - "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", - "license": "MIT", - "dependencies": { - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/engine.io-client": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", - "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1", - "xmlhttprequest-ssl": "~2.1.1" - } - }, - "node_modules/engine.io-client/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/es-abstract": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", - "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", - "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.6", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.4", - "safe-array-concat": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz", - "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.1", - "@eslint/core": "^0.15.2", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.36.0", - "@eslint/plugin-kit": "^0.3.5", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-config-next": { - "version": "15.5.4", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.4.tgz", - "integrity": "sha512-BzgVVuT3kfJes8i2GHenC1SRJ+W3BTML11lAOYFOOPzrk2xp66jBOAGEFRw+3LkYCln5UzvFsLhojrshb5Zfaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@next/eslint-plugin-next": "15.5.4", - "@rushstack/eslint-patch": "^1.10.3", - "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsx-a11y": "^6.10.0", - "eslint-plugin-react": "^7.37.0", - "eslint-plugin-react-hooks": "^5.0.0" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", - "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.4.0", - "get-tsconfig": "^4.10.0", - "is-bun-module": "^2.0.0", - "stable-hash": "^0.0.5", - "tinyglobby": "^0.2.13", - "unrs-resolver": "^1.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-import-resolver-typescript" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", - "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", - "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", - "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "aria-query": "^5.3.2", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.10.0", - "axobject-query": "^4.1.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.1" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.37.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", - "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.3", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.2.1", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.9", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.1", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.12", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", - "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/goober": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz", - "integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==", - "license": "MIT", - "peerDependencies": { - "csstype": "^3.0.10" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/howler": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz", - "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==", - "license": "MIT" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bun-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", - "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.7.1" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/iterator.prototype": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", - "has-symbols": "^1.1.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "license": "MIT", - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-postinstall": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", - "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", - "dev": true, - "license": "MIT", - "bin": { - "napi-postinstall": "lib/cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/next": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.33.tgz", - "integrity": "sha512-GiKHLsD00t4ACm1p00VgrI0rUFAC9cRDGReKyERlM57aeEZkOQGcZTpIbsGn0b562FTPJWmYfKwplfO9EaT6ng==", - "license": "MIT", - "dependencies": { - "@next/env": "14.2.33", - "@swc/helpers": "0.5.5", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", - "postcss": "8.4.31", - "styled-jsx": "5.1.1" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=18.17.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.33", - "@next/swc-darwin-x64": "14.2.33", - "@next/swc-linux-arm64-gnu": "14.2.33", - "@next/swc-linux-arm64-musl": "14.2.33", - "@next/swc-linux-x64-gnu": "14.2.33", - "@next/swc-linux-x64-musl": "14.2.33", - "@next/swc-win32-arm64-msvc": "14.2.33", - "@next/swc-win32-ia32-msvc": "14.2.33", - "@next/swc-win32-x64-msvc": "14.2.33" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "@playwright/test": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/node-releases": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", - "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", - "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", - "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-plugin-tailwindcss": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.14.tgz", - "integrity": "sha512-Puaz+wPUAhFp8Lo9HuciYKM2Y2XExESjeT+9NQoVFXZsPPnc9VYss2SpxdQ6vbatmt8/4+SN0oe0I1cPDABg9Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@ianvs/prettier-plugin-sort-imports": "*", - "@prettier/plugin-pug": "*", - "@shopify/prettier-plugin-liquid": "*", - "@trivago/prettier-plugin-sort-imports": "*", - "@zackad/prettier-plugin-twig-melody": "*", - "prettier": "^3.0", - "prettier-plugin-astro": "*", - "prettier-plugin-css-order": "*", - "prettier-plugin-import-sort": "*", - "prettier-plugin-jsdoc": "*", - "prettier-plugin-marko": "*", - "prettier-plugin-organize-attributes": "*", - "prettier-plugin-organize-imports": "*", - "prettier-plugin-sort-imports": "*", - "prettier-plugin-style-order": "*", - "prettier-plugin-svelte": "*" - }, - "peerDependenciesMeta": { - "@ianvs/prettier-plugin-sort-imports": { - "optional": true - }, - "@prettier/plugin-pug": { - "optional": true - }, - "@shopify/prettier-plugin-liquid": { - "optional": true - }, - "@trivago/prettier-plugin-sort-imports": { - "optional": true - }, - "@zackad/prettier-plugin-twig-melody": { - "optional": true - }, - "prettier-plugin-astro": { - "optional": true - }, - "prettier-plugin-css-order": { - "optional": true - }, - "prettier-plugin-import-sort": { - "optional": true - }, - "prettier-plugin-jsdoc": { - "optional": true - }, - "prettier-plugin-marko": { - "optional": true - }, - "prettier-plugin-organize-attributes": { - "optional": true - }, - "prettier-plugin-organize-imports": { - "optional": true - }, - "prettier-plugin-sort-imports": { - "optional": true - }, - "prettier-plugin-style-order": { - "optional": true - }, - "prettier-plugin-svelte": { - "optional": true - } - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/property-expr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", - "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", - "license": "MIT" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-confetti": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.4.0.tgz", - "integrity": "sha512-5MdGUcqxrTU26I2EU7ltkWPwxvucQTuqMm8dUz72z2YMqTD6s9vMcDUysk7n9jnC+lXuCPeJJ7Knf98VEYE9Rg==", - "license": "MIT", - "dependencies": { - "tween-functions": "^1.2.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": "^16.3.0 || ^17.0.1 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-hot-toast": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", - "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==", - "license": "MIT", - "dependencies": { - "csstype": "^3.1.3", - "goober": "^2.1.16" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": ">=16", - "react-dom": ">=16" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "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", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/socket.io": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", - "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.6.0", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", - "license": "MIT", - "dependencies": { - "debug": "~4.3.4", - "ws": "~8.17.1" - } - }, - "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io-client": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", - "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.2", - "engine.io-client": "~6.6.1", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-client/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spawn-command": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", - "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==" - }, - "node_modules/stable-hash": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", - "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", - "dev": true, - "license": "MIT" - }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.includes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", - "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", - "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "license": "MIT", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tailwindcss": { - "version": "3.4.17", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", - "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.6.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.6", - "lilconfig": "^3.1.3", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2", - "postcss-nested": "^6.2.0", - "postcss-selector-parser": "^6.1.2", - "resolve": "^1.22.8", - "sucrase": "^3.35.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss/node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tiny-case": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", - "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", - "license": "MIT" - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tween-functions": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", - "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", - "license": "BSD" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", - "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", - "license": "MIT" - }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "napi-postinstall": "^0.3.0" - }, - "funding": { - "url": "https://opencollective.com/unrs-resolver" - }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/use-sound": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/use-sound/-/use-sound-4.0.4.tgz", - "integrity": "sha512-SW81yRUu3K0rJHW0WVANCAK581A2qgD97+QrLxPhlAhvdIAIgw2J9d1VThdbHmPHjzCbwKE/is82V88sgFdjCg==", - "license": "MIT", - "dependencies": { - "howler": "^2.2.4" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xmlhttprequest-ssl": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", - "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yup": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz", - "integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==", - "license": "MIT", - "dependencies": { - "property-expr": "^2.0.5", - "tiny-case": "^1.0.3", - "toposort": "^2.0.2", - "type-fest": "^2.19.0" - } - }, - "node_modules/yup/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/package.json b/package.json index f48955f..eee3bf7 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,15 @@ { "name": "rahoot", - "version": "0.1.0", - "private": true, "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "socket": "node ./socket/index.js", - "all": "npm run build && concurrently --kill-others \"npm run start\" \"npm run socket\"", - "all-dev": "concurrently --kill-others \"npm run dev\" \"npm run socket\"", - "lint": "eslint .", - "next:lint": "next lint" - }, - "dependencies": { - "clsx": "^2.1.0", - "concurrently": "^8.2.2", - "next": "^14.2.32", - "react": "^18", - "react-confetti": "^6.1.0", - "react-dom": "^18", - "react-hot-toast": "^2.4.1", - "socket.io": "^4.7.4", - "socket.io-client": "^4.7.4", - "use-sound": "^4.0.1", - "yup": "^1.3.3" + "dev": "dotenv -e .env -- pnpm -r --parallel dev", + "dev:web": "dotenv -e .env -- pnpm --filter web dev", + "dev:socket": "dotenv -e .env -- pnpm --filter socket dev", + "build": "pnpm -r run build", + "start": "pnpm -r --parallel run start", + "clean": "pnpm -r exec rm -rf dist node_modules" }, "devDependencies": { - "autoprefixer": "^10.0.1", - "eslint": "^9.36.0", - "eslint-config-next": "^15.5.4", - "postcss": "^8", - "prettier-plugin-tailwindcss": "^0.5.14", - "tailwindcss": "^3.3.0" + "dotenv-cli": "^10.0.0", + "typescript": "^5.0.0" } } diff --git a/packages/common/.gitignore b/packages/common/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/packages/common/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/packages/common/package.json b/packages/common/package.json new file mode 100644 index 0000000..be7ddc7 --- /dev/null +++ b/packages/common/package.json @@ -0,0 +1,13 @@ +{ + "name": "@rahoot/common", + "version": "1.0.0", + "type": "module", + "dependencies": { + "socket.io": "^4.8.1", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/node": "^20.11.0", + "typescript": "^5.3.3" + } +} diff --git a/packages/common/src/types/game/index.ts b/packages/common/src/types/game/index.ts new file mode 100644 index 0000000..06698a8 --- /dev/null +++ b/packages/common/src/types/game/index.ts @@ -0,0 +1,30 @@ +export type Player = { + id: string + username: string + points: number +} + +export type Answer = { + playerId: string + answerId: number + points: number +} + +export type Quizz = { + subject: string + questions: { + question: string + image?: string + answers: string[] + solution: number + cooldown: number + time: number + }[] +} + +export type QuizzWithId = Quizz & { id: string } + +export type GameUpdateQuestion = { + current: number + total: number +} diff --git a/packages/common/src/types/game/socket.ts b/packages/common/src/types/game/socket.ts new file mode 100644 index 0000000..5a83c1f --- /dev/null +++ b/packages/common/src/types/game/socket.ts @@ -0,0 +1,72 @@ +import { Server as ServerIO, Socket as SocketIO } from "socket.io" +import { Player, QuizzWithId } from "." +import { Status, StatusDataMap } from "./status" + +export type Server = ServerIO +export type Socket = SocketIO + +export type Message = { + gameId?: string + status: K + data: StatusDataMap[K] +} + +export type MessageWithoutStatus = { + gameId?: string + data: T +} + +export type MessageGameId = { + gameId?: string +} + +export interface ServerToClientEvents { + // Game events + "game:status": (data: { name: Status; data: StatusDataMap[Status] }) => void + "game:successRoom": (data: string) => void + "game:successJoin": (gameId: string) => void + "game:totalPlayers": (count: number) => void + "game:errorMessage": (message: string) => void + "game:startCooldown": () => void + "game:cooldown": (count: number) => void + "game:kick": () => void + "game:reset": () => void + "game:updateQuestion": (data: { current: number; total: number }) => void + "game:playerAnswer": (count: number) => void + "player:updateLeaderboard": (data: { leaderboard: Player[] }) => void + + // Manager events + "manager:quizzList": (quizzList: QuizzWithId[]) => void + "manager:gameCreated": (data: { gameId: string; inviteCode: string }) => void + "manager:statusUpdate": (data: { + status: Status + data: StatusDataMap[Status] + }) => void + "manager:newPlayer": (player: Player) => void + "manager:removePlayer": (playerId: string) => void + "manager:errorMessage": (message: string) => void + "manager:playerKicked": (playerId: string) => void +} + +export interface ClientToServerEvents { + // Manager actions + "game:create": (quizzId: string) => void + "manager:auth": (password: string) => void + "manager:kickPlayer": ( + message: MessageWithoutStatus<{ playerId: string }> + ) => void + "manager:startGame": (message: MessageGameId) => void + "manager:abortQuiz": (message: MessageGameId) => void + "manager:nextQuestion": (message: MessageGameId) => void + "manager:showLeaderboard": (message: MessageGameId) => void + + // Player actions + "player:join": (inviteCode: string) => void + "player:login": (message: MessageWithoutStatus<{ username: string }>) => void + "player:selectedAnswer": ( + message: MessageWithoutStatus<{ answerKey: number }> + ) => void + + // Common + disconnect: () => void +} diff --git a/packages/common/src/types/game/status.ts b/packages/common/src/types/game/status.ts new file mode 100644 index 0000000..dfcc5b2 --- /dev/null +++ b/packages/common/src/types/game/status.ts @@ -0,0 +1,58 @@ +import { Player } from "."; + +export enum Status { + SHOW_ROOM = "SHOW_ROOM", + SHOW_START = "SHOW_START", + SHOW_PREPARED = "SHOW_PREPARED", + SHOW_QUESTION = "SHOW_QUESTION", + SELECT_ANSWER = "SELECT_ANSWER", + SHOW_RESULT = "SHOW_RESULT", + SHOW_RESPONSES = "SHOW_RESPONSES", + SHOW_LEADERBOARD = "SHOW_LEADERBOARD", + FINISHED = "FINISHED", + WAIT = "WAIT", +} + + +export type CommonStatusDataMap = { + SHOW_START: { time: number; subject: string } + SHOW_PREPARED: { totalAnswers: number; questionNumber: number } + SHOW_QUESTION: { question: string; image?: string; cooldown: number } + SELECT_ANSWER: { + question: string + answers: string[] + image?: string + time: number + totalPlayer: number + } + SHOW_RESULT: { + correct: boolean + message: string + points: number + myPoints: number + rank: number + aheadOfMe: string | null + } + WAIT: { text: string } + FINISHED: { subject: string; top: Player[] } +} + +type ManagerExtraStatus = { + SHOW_ROOM: { text: string; inviteCode?: string } + SHOW_RESPONSES: { + question: string + responses: Record + correct: number + answers: string[] + image?: string + } + SHOW_LEADERBOARD: { leaderboard: Player[] } +} + +type PlayerExtraStatus = { + WAIT: { text: string } +} + +export type PlayerStatusDataMap = CommonStatusDataMap & PlayerExtraStatus +export type ManagerStatusDataMap = CommonStatusDataMap & ManagerExtraStatus +export type StatusDataMap = PlayerStatusDataMap & ManagerStatusDataMap diff --git a/packages/common/tsconfig.json b/packages/common/tsconfig.json new file mode 100644 index 0000000..3eb1a0e --- /dev/null +++ b/packages/common/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "skipLibCheck": true, + "noEmit": true + } +} diff --git a/packages/socket/.gitignore b/packages/socket/.gitignore new file mode 100644 index 0000000..76add87 --- /dev/null +++ b/packages/socket/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/packages/socket/esbuild.config.js b/packages/socket/esbuild.config.js new file mode 100644 index 0000000..4b258ab --- /dev/null +++ b/packages/socket/esbuild.config.js @@ -0,0 +1,19 @@ +import esbuild from "esbuild" +import path from "path" + +export const config = { + entryPoints: ["src/index.ts"], + bundle: true, + minify: true, + platform: "node", + outfile: "dist/index.cjs", + sourcemap: true, + define: { + "process.env.NODE_ENV": '"production"', + }, + alias: { + "@": path.resolve("./src"), + }, +} + +esbuild.build(config) diff --git a/packages/socket/package.json b/packages/socket/package.json new file mode 100644 index 0000000..f9b4205 --- /dev/null +++ b/packages/socket/package.json @@ -0,0 +1,24 @@ +{ + "name": "@rahoot/socket", + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "tsx watch src/index.ts", + "build": "node esbuild.config.js", + "start": "node dist/index.cjs" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@rahoot/common": "workspace:*", + "@t3-oss/env-core": "^0.13.8", + "socket.io": "^4.8.1", + "uuid": "^13.0.0", + "zod": "^4.1.11" + }, + "devDependencies": { + "esbuild": "^0.25.10", + "tsx": "^4.20.6" + } +} diff --git a/packages/socket/src/env.ts b/packages/socket/src/env.ts new file mode 100644 index 0000000..b64a0ab --- /dev/null +++ b/packages/socket/src/env.ts @@ -0,0 +1,14 @@ +import { createEnv } from "@t3-oss/env-core" +import { z } from "zod/v4" + +const env = createEnv({ + server: { + SOCKER_PORT: z.string().optional().default("3001"), + }, + + runtimeEnv: { + SOCKER_PORT: process.env.SOCKER_PORT, + }, +}) + +export default env diff --git a/packages/socket/src/index.ts b/packages/socket/src/index.ts new file mode 100644 index 0000000..cf051ba --- /dev/null +++ b/packages/socket/src/index.ts @@ -0,0 +1,159 @@ +import { Server, Socket } from "@rahoot/common/types/game/socket" +import env from "@rahoot/socket/env" +import Config from "@rahoot/socket/services/config" +import Game from "@rahoot/socket/services/game" +import { inviteCodeValidator } from "@rahoot/socket/utils/validator" +import { Server as ServerIO } from "socket.io" + +const io: Server = new ServerIO() +Config.init() + +let games: Game[] = [] +const port = env.SOCKER_PORT || 3001 + +console.log(`Socket server running on port ${port}`) +io.listen(Number(port)) + +function withGame( + gameId: string | undefined, + socket: Socket, + games: Game[], + handler: (game: Game) => T +): T | void { + let game = null + + if (gameId) { + game = games.find((g) => g.gameId === gameId) + } else { + game = games.find( + (g) => + g.players.find((p) => p.id === socket.id) || g.managerId === socket.id + ) + } + + if (!game) { + socket.emit("game:errorMessage", "Game not found") + return + } + + return handler(game) +} + +io.on("connection", (socket) => { + console.log(`A user connected ${socket.id}`) + console.log(socket.handshake.auth) + + socket.on("manager:auth", (password) => { + try { + const config = Config.game() + + if (password !== config.managerPassword) { + socket.emit("manager:errorMessage", "Invalid password") + return + } + + socket.emit("manager:quizzList", Config.quizz()) + } catch (error) { + console.error("Failed to read game config:", error) + socket.emit("manager:errorMessage", "Failed to read game config") + } + }) + + socket.on("game:create", (quizzId) => { + const quizzList = Config.quizz() + const quizz = quizzList.find((q) => q.id === quizzId) + + if (!quizz) { + socket.emit("game:errorMessage", "Quizz not found") + return + } + + const game = new Game(io, socket, quizz) + + games.push(game) + }) + + socket.on("player:join", async (inviteCode) => { + const result = inviteCodeValidator.safeParse(inviteCode) + + if (result.error) { + socket.emit("game:errorMessage", result.error.issues[0].message) + return + } + + const game = games.find((g) => g.inviteCode === inviteCode) + + if (!game) { + socket.emit("game:errorMessage", "Game not found") + + return + } + + socket.emit("game:successRoom", game.gameId) + }) + + socket.on("player:login", ({ gameId, data }) => + withGame(gameId, socket, games, (game) => game.join(socket, data.username)) + ) + + socket.on("manager:kickPlayer", ({ gameId, data }) => + withGame(gameId, socket, games, (game) => + game.kickPlayer(socket, data.playerId) + ) + ) + + socket.on("manager:startGame", ({ gameId }) => + withGame(gameId, socket, games, (game) => game.start(socket)) + ) + + socket.on("player:selectedAnswer", ({ gameId, data }) => + withGame(gameId, socket, games, (game) => + game.selectAnswer(socket, data.answerKey) + ) + ) + + socket.on("manager:abortQuiz", ({ gameId }) => + withGame(gameId, socket, games, (game) => game.abortRound(socket)) + ) + + socket.on("manager:nextQuestion", ({ gameId }) => + withGame(gameId, socket, games, (game) => game.nextRound(socket)) + ) + + socket.on("manager:showLeaderboard", ({ gameId }) => + withGame(gameId, socket, games, (game) => game.showLeaderboard(socket)) + ) + + socket.on("disconnect", () => { + console.log(`user disconnected ${socket.id}`) + const managerGame = games.find((g) => g.managerId === socket.id) + + if (managerGame) { + console.log("Reset game (manager disconnected)") + + managerGame.abortCooldown() + io.to(managerGame.gameId).emit("game:reset") + + games = games.filter((g) => g.gameId !== managerGame.gameId) + + return + } + + const game = games.find((g) => g.players.some((p) => p.id === socket.id)) + + if (game) { + const player = game.players.find((p) => p.id === socket.id) + + if (player) { + game.players = game.players.filter((p) => p.id !== socket.id) + + io.to(game.managerId).emit("manager:removePlayer", player.id) + io.to(game.gameId).emit("game:totalPlayers", game.players.length) + + console.log( + `Removed player ${player.username} from game ${game.gameId}` + ) + } + } + }) +}) diff --git a/packages/socket/src/services/config.ts b/packages/socket/src/services/config.ts new file mode 100644 index 0000000..9c1bd50 --- /dev/null +++ b/packages/socket/src/services/config.ts @@ -0,0 +1,110 @@ +import { QuizzWithId } from "@rahoot/common/types/game" +import fs from "fs" +import { resolve } from "path" + +const getPath = (path: string) => resolve(process.cwd(), "../../config", path) + +class Config { + static init() { + const isGameConfigExists = fs.existsSync(getPath("game.json")) + if (!isGameConfigExists) { + fs.writeFileSync( + getPath("game.json"), + JSON.stringify( + { + managerPassword: "PASSWORD", + music: true, + }, + null, + 2 + ) + ) + } + + const isQuizzExists = fs.existsSync(getPath("quizz")) + if (!isQuizzExists) { + fs.mkdirSync(getPath("quizz")) + + fs.writeFileSync( + getPath("quizz/example.json"), + JSON.stringify( + { + subject: "Example Quizz", + questions: [ + { + question: "What is good answer ?", + answers: ["No", "Good answer", "No", "No"], + solution: 1, + cooldown: 5, + time: 15, + }, + { + question: "What is good answer with image ?", + answers: ["No", "No", "No", "Good answer"], + image: "https://placehold.co/600x400.png", + solution: 3, + cooldown: 5, + time: 20, + }, + { + question: "What is good answer with two answers ?", + answers: ["Good answer", "No"], + image: "https://placehold.co/600x400.png", + solution: 0, + cooldown: 5, + time: 20, + }, + ], + }, + null, + 2 + ) + ) + } + } + + static game() { + const isExists = fs.existsSync(getPath("game.json")) + if (!isExists) { + throw new Error("Game config not found") + } + + try { + const config = fs.readFileSync(getPath("game.json"), "utf-8") + return JSON.parse(config) + } catch (error) { + console.error("Failed to read game config:", error) + } + } + + static quizz() { + const isExists = fs.existsSync(getPath("quizz")) + if (!isExists) { + return [] + } + + try { + const files = fs + .readdirSync(getPath("quizz")) + .filter((file) => file.endsWith(".json")) + + const quizz: QuizzWithId[] = files.map((file) => { + const data = fs.readFileSync(getPath(`quizz/${file}`), "utf-8") + const config = JSON.parse(data) + + const id = file.replace(".json", "") + + return { + id, + ...config, + } + }) + return quizz || [] + } catch (error) { + console.error("Failed to read quizz config:", error) + return [] + } + } +} + +export default Config diff --git a/packages/socket/src/services/game.ts b/packages/socket/src/services/game.ts new file mode 100644 index 0000000..b66c68f --- /dev/null +++ b/packages/socket/src/services/game.ts @@ -0,0 +1,384 @@ +import { Answer, Player, Quizz } from "@rahoot/common/types/game" +import { Server, Socket } from "@rahoot/common/types/game/socket" +import { Status } from "@rahoot/common/types/game/status" +import createInviteCode from "@rahoot/socket/utils/inviteCode" +import { v4 as uuid } from "uuid" +import sleep from "../utils/sleep" + +class Game { + io: Server + + gameId: string + managerId: string + inviteCode: string + started: boolean + status: Status + quizz: Quizz + players: Player[] + + round: { + currentQuestion: number + playersAnswers: Answer[] + startTime: number + } + + cooldown: { + active: boolean + ms: number + } + + constructor(io: Server, socket: Socket, quizz: Quizz) { + if (!io) { + throw new Error("Socket server not initialized") + } + + this.io = io + this.gameId = uuid() + this.managerId = "" + this.inviteCode = "" + this.started = false + this.status = Status.SHOW_START + this.players = [] + + this.round = { + playersAnswers: [], + currentQuestion: 0, + startTime: 0, + } + + this.cooldown = { + active: false, + ms: 0, + } + + const roomInvite = createInviteCode() + this.inviteCode = roomInvite + this.managerId = socket.id + this.quizz = quizz + + socket.join(this.gameId) + socket.emit("manager:gameCreated", { + gameId: this.gameId, + inviteCode: roomInvite, + }) + + console.log( + `New game created: ${roomInvite} subject: ${this.quizz.subject}` + ) + } + + join(socket: Socket, username: string) { + socket.join(this.gameId) + + const playerData = { + id: socket.id, + username: username, + points: 0, + } + + this.players.push(playerData) + + this.io.to(this.managerId).emit("manager:newPlayer", playerData) + this.io.to(this.gameId).emit("game:totalPlayers", this.players.length) + + socket.emit("game:successJoin", this.gameId) + } + + kickPlayer(socket: Socket, playerId: string) { + if (this.managerId !== socket.id) { + return + } + + const player = this.players.find((p) => p.id === playerId) + + if (!player) { + return + } + + this.players = this.players.filter((p) => p.id !== playerId) + + this.io.in(playerId).socketsLeave(this.gameId) + this.io.to(player.id).emit("game:kick") + this.io.to(this.managerId).emit("manager:playerKicked", player.id) + + this.io.to(this.gameId).emit("game:totalPlayers", this.players.length) + } + + async startCooldown(seconds: number) { + if (this.cooldown.active) { + return + } + + this.cooldown.active = true + + let count = seconds - 1 + + return new Promise((resolve) => { + const cooldownTimeout = setInterval(() => { + if (!this.cooldown.active || count <= 0) { + this.cooldown.active = false + clearInterval(cooldownTimeout) + resolve() + } else { + this.io.to(this.gameId).emit("game:cooldown", count) + count -= 1 + } + }, 1000) + }) + } + + async abortCooldown() { + if (this.cooldown.active) { + this.cooldown.active = false + } + } + + async start(socket: Socket) { + if (this.managerId !== socket.id) { + return + } + + if (this.started) { + return + } + + this.started = true + this.io.to(this.gameId).emit("game:status", { + name: Status.SHOW_START, + data: { + time: 3, + subject: this.quizz.subject, + }, + }) + + await sleep(3) + + this.io.to(this.gameId).emit("game:startCooldown") + + await this.startCooldown(3) + + this.newRound() + } + + async newRound() { + const question = this.quizz.questions[this.round.currentQuestion] + + if (!this.started) { + return + } + + this.io.to(this.gameId).emit("game:updateQuestion", { + current: this.round.currentQuestion + 1, + total: this.quizz.questions.length, + }) + + this.io.to(this.gameId).emit("game:status", { + name: Status.SHOW_PREPARED, + data: { + totalAnswers: question.answers.length, + questionNumber: this.round.currentQuestion + 1, + }, + }) + + await sleep(2) + + if (!this.started) { + return + } + + this.io.to(this.gameId).emit("game:status", { + name: Status.SHOW_QUESTION, + data: { + question: question.question, + image: question.image, + cooldown: question.cooldown, + }, + }) + + await sleep(question.cooldown) + + if (!this.started) { + return + } + + this.round.startTime = Date.now() + + this.io.to(this.gameId).emit("game:status", { + name: Status.SELECT_ANSWER, + data: { + question: question.question, + answers: question.answers, + image: question.image, + time: question.time, + totalPlayer: this.players.length, + }, + }) + + await this.startCooldown(question.time) + + if (!this.started) { + return + } + + this.players = this.players.map((player) => { + const playerAnswer = this.round.playersAnswers.find( + (a) => a.playerId === player.id + ) + + const isCorrect = playerAnswer + ? playerAnswer.answerId === question.solution + : false + + const points = + playerAnswer && isCorrect + ? Math.round(playerAnswer && playerAnswer.points) + : 0 + + player.points += points + + const sortPlayers = this.players.sort((a, b) => b.points - a.points) + + const rank = sortPlayers.findIndex((p) => p.id === player.id) + 1 + const aheadPlayer = sortPlayers[rank - 2] + + this.io.to(player.id).emit("game:status", { + name: Status.SHOW_RESULT, + data: { + correct: isCorrect, + message: isCorrect ? "Nice !" : "Too bad", + points, + myPoints: player.points, + rank, + aheadOfMe: aheadPlayer ? aheadPlayer.username : null, + }, + }) + + return player + }) + + const totalType = this.round.playersAnswers.reduce( + (acc: Record, { answerId }) => { + acc[answerId] = (acc[answerId] || 0) + 1 + return acc + }, + {} + ) + + // Manager + this.io.to(this.gameId).emit("game:status", { + name: Status.SHOW_RESPONSES, + data: { + question: question.question, + responses: totalType, + correct: question.solution, + answers: question.answers, + image: question.image, + }, + }) + + this.round.playersAnswers = [] + } + + timeToPoint(startTime: number, secondes: number) { + let points = 1000 + + const actualTime = Date.now() + const tempsPasseEnSecondes = (actualTime - startTime) / 1000 + + points -= (1000 / secondes) * tempsPasseEnSecondes + points = Math.max(0, points) + + return points + } + + async selectAnswer(socket: Socket, answerId: number) { + const player = this.players.find((player) => player.id === socket.id) + + const question = this.quizz.questions[this.round.currentQuestion] + + if (!player) { + return + } + + if (this.round.playersAnswers.find((p) => p.playerId === socket.id)) { + return + } + + this.round.playersAnswers.push({ + playerId: player.id, + answerId, + points: this.timeToPoint(this.round.startTime, question.time), + }) + + socket.emit("game:status", { + name: Status.WAIT, + data: { text: "Waiting for the players to answer" }, + }) + socket + .to(this.gameId) + .emit("game:playerAnswer", this.round.playersAnswers.length) + + this.io.to(this.gameId).emit("game:totalPlayers", this.players.length) + + if (this.round.playersAnswers.length === this.players.length) { + this.abortCooldown() + } + } + + nextRound(socket: Socket) { + if (!this.started) { + return + } + + if (socket.id !== this.managerId) { + return + } + + if (!this.quizz.questions[this.round.currentQuestion + 1]) { + return + } + + this.round.currentQuestion += 1 + this.newRound() + } + + abortRound(socket: Socket) { + if (!this.started) { + return + } + + if (socket.id !== this.managerId) { + return + } + + this.abortCooldown() + } + + showLeaderboard(socket: Socket) { + const isLastRound = + this.round.currentQuestion + 1 === this.quizz.questions.length + + const sortedPlayers = this.players.sort((a, b) => b.points - a.points) + + if (isLastRound) { + socket.emit("game:status", { + name: Status.FINISHED, + data: { + subject: this.quizz.subject, + top: sortedPlayers.slice(0, 3), + }, + }) + + return + } + + socket.emit("game:status", { + name: Status.SHOW_LEADERBOARD, + data: { + leaderboard: sortedPlayers.slice(0, 5), + }, + }) + } +} + +export default Game diff --git a/socket/utils/generateRoomId.js b/packages/socket/src/utils/inviteCode.ts similarity index 78% rename from socket/utils/generateRoomId.js rename to packages/socket/src/utils/inviteCode.ts index 5367081..f6837ee 100644 --- a/socket/utils/generateRoomId.js +++ b/packages/socket/src/utils/inviteCode.ts @@ -1,4 +1,4 @@ -const generateRoomId = (length = 6) => { +const createInviteCode = (length = 6) => { let result = "" const characters = "0123456789" const charactersLength = characters.length @@ -11,4 +11,4 @@ const generateRoomId = (length = 6) => { return result } -export default generateRoomId +export default createInviteCode diff --git a/packages/socket/src/utils/sleep.ts b/packages/socket/src/utils/sleep.ts new file mode 100644 index 0000000..f6116e2 --- /dev/null +++ b/packages/socket/src/utils/sleep.ts @@ -0,0 +1,4 @@ +export const sleep = (sec: number) => + new Promise((r) => void setTimeout(r, sec * 1000)) + +export default sleep diff --git a/packages/socket/src/utils/validator.ts b/packages/socket/src/utils/validator.ts new file mode 100644 index 0000000..28c1136 --- /dev/null +++ b/packages/socket/src/utils/validator.ts @@ -0,0 +1,8 @@ +import z from "zod" + +export const usernameValidator = z + .string() + .min(4, "Username cannot be less than 4 characters") + .max(20, "Username cannot exceed 20 characters") + +export const inviteCodeValidator = z.string().length(6, "Invalid invite code") diff --git a/packages/socket/tsconfig.json b/packages/socket/tsconfig.json new file mode 100644 index 0000000..42ed9cb --- /dev/null +++ b/packages/socket/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "skipLibCheck": true, + "noEmit": true + } +} diff --git a/packages/web/.gitignore b/packages/web/.gitignore new file mode 100644 index 0000000..0c82063 --- /dev/null +++ b/packages/web/.gitignore @@ -0,0 +1,42 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build +dist + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/.prettierrc.json b/packages/web/.prettierrc.json similarity index 100% rename from .prettierrc.json rename to packages/web/.prettierrc.json diff --git a/packages/web/README.md b/packages/web/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/packages/web/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/eslint.config.mjs b/packages/web/eslint.config.mjs similarity index 96% rename from eslint.config.mjs rename to packages/web/eslint.config.mjs index 86333c6..8df583a 100644 --- a/eslint.config.mjs +++ b/packages/web/eslint.config.mjs @@ -1,5 +1,6 @@ -// eslint.config.js import nextPlugin from "@next/eslint-plugin-next" +import tsEslintPlugin from "@typescript-eslint/eslint-plugin" +import tsEslintParser from "@typescript-eslint/parser" import reactPlugin from "eslint-plugin-react" import reactHooksPlugin from "eslint-plugin-react-hooks" import { defineConfig } from "eslint/config" @@ -10,10 +11,11 @@ export default defineConfig([ ignores: ["**/node_modules/**", "**/.next/**"], }, { - files: ["**/*.js", "**/*.jsx"], + files: ["**/*.ts", "**/*.tsx"], languageOptions: { ecmaVersion: "latest", sourceType: "module", + parser: tsEslintParser, parserOptions: { ecmaFeatures: { jsx: true }, }, @@ -23,6 +25,7 @@ export default defineConfig([ }, }, plugins: { + "@typescript-eslint": tsEslintPlugin, react: reactPlugin, "react-hooks": reactHooksPlugin, "@next/next": nextPlugin, diff --git a/packages/web/next.config.mjs b/packages/web/next.config.mjs new file mode 100644 index 0000000..92337ee --- /dev/null +++ b/packages/web/next.config.mjs @@ -0,0 +1,10 @@ +const nextConfig = { + output: "standalone", + productionBrowserSourceMaps: false, + transpilePackages: ["packages/*", "@t3-oss/env-nextjs"], + eslint: { + ignoreDuringBuilds: true, + }, +} + +export default nextConfig diff --git a/packages/web/package.json b/packages/web/package.json new file mode 100644 index 0000000..71aca3e --- /dev/null +++ b/packages/web/package.json @@ -0,0 +1,45 @@ +{ + "name": "@rahoot/web", + "version": "1.0.0", + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "node .next/standalone/packages/web/server.js", + "lint": "eslint" + }, + "dependencies": { + "@rahoot/common": "workspace:*", + "@rahoot/socket": "workspace:*", + "@t3-oss/env-nextjs": "^0.13.8", + "clsx": "^2.1.1", + "ky": "^1.11.0", + "next": "15.5.4", + "react": "19.1.0", + "react-confetti": "^6.4.0", + "react-dom": "19.1.0", + "react-hot-toast": "^2.6.0", + "socket.io-client": "^4.8.1", + "use-sound": "^5.0.0", + "yup": "^1.7.1", + "zod": "^4.1.12", + "zustand": "^5.0.8" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "@typescript-eslint/eslint-plugin": "^8.45.0", + "@typescript-eslint/parser": "^8.45.0", + "eslint": "^9", + "eslint-config-next": "15.5.4", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^6.1.1", + "globals": "^16.4.0", + "prettier": "^3.6.2", + "prettier-plugin-tailwindcss": "^0.6.14", + "tailwindcss": "^4", + "typescript": "^5" + } +} diff --git a/packages/web/postcss.config.mjs b/packages/web/postcss.config.mjs new file mode 100644 index 0000000..c7bcb4b --- /dev/null +++ b/packages/web/postcss.config.mjs @@ -0,0 +1,5 @@ +const config = { + plugins: ["@tailwindcss/postcss"], +}; + +export default config; diff --git a/public/icon.svg b/packages/web/public/icon.svg similarity index 100% rename from public/icon.svg rename to packages/web/public/icon.svg diff --git a/public/sounds/answersMusic.mp3 b/packages/web/public/sounds/answersMusic.mp3 similarity index 100% rename from public/sounds/answersMusic.mp3 rename to packages/web/public/sounds/answersMusic.mp3 diff --git a/public/sounds/answersSound.mp3 b/packages/web/public/sounds/answersSound.mp3 similarity index 100% rename from public/sounds/answersSound.mp3 rename to packages/web/public/sounds/answersSound.mp3 diff --git a/public/sounds/boump.mp3 b/packages/web/public/sounds/boump.mp3 similarity index 100% rename from public/sounds/boump.mp3 rename to packages/web/public/sounds/boump.mp3 diff --git a/public/sounds/first.mp3 b/packages/web/public/sounds/first.mp3 similarity index 100% rename from public/sounds/first.mp3 rename to packages/web/public/sounds/first.mp3 diff --git a/public/sounds/results.mp3 b/packages/web/public/sounds/results.mp3 similarity index 100% rename from public/sounds/results.mp3 rename to packages/web/public/sounds/results.mp3 diff --git a/public/sounds/second.mp3 b/packages/web/public/sounds/second.mp3 similarity index 100% rename from public/sounds/second.mp3 rename to packages/web/public/sounds/second.mp3 diff --git a/public/sounds/show.mp3 b/packages/web/public/sounds/show.mp3 similarity index 100% rename from public/sounds/show.mp3 rename to packages/web/public/sounds/show.mp3 diff --git a/public/sounds/snearRoll.mp3 b/packages/web/public/sounds/snearRoll.mp3 similarity index 100% rename from public/sounds/snearRoll.mp3 rename to packages/web/public/sounds/snearRoll.mp3 diff --git a/public/sounds/three.mp3 b/packages/web/public/sounds/three.mp3 similarity index 100% rename from public/sounds/three.mp3 rename to packages/web/public/sounds/three.mp3 diff --git a/packages/web/src/app/(auth)/layout.tsx b/packages/web/src/app/(auth)/layout.tsx new file mode 100644 index 0000000..379d167 --- /dev/null +++ b/packages/web/src/app/(auth)/layout.tsx @@ -0,0 +1,17 @@ +"use client" + +import { useSocket } from "@rahoot/web/contexts/socketProvider" +import { PropsWithChildren, useEffect } from "react" + +const AuthLayout = ({ children }: PropsWithChildren) => { + const { isConnected, connect } = useSocket() + useEffect(() => { + if (!isConnected) { + connect() + } + }, [connect, isConnected]) + + return children +} + +export default AuthLayout diff --git a/packages/web/src/app/(auth)/manager/page.tsx b/packages/web/src/app/(auth)/manager/page.tsx new file mode 100644 index 0000000..507b27d --- /dev/null +++ b/packages/web/src/app/(auth)/manager/page.tsx @@ -0,0 +1,43 @@ +"use client" + +import { QuizzWithId } from "@rahoot/common/types/game" +import ManagerPassword from "@rahoot/web/components/game/create/ManagerPassword" +import SelectQuizz from "@rahoot/web/components/game/create/SelectQuizz" +import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" +import { useManagerGameStore } from "@rahoot/web/stores/game" +import { useRouter } from "next/navigation" +import { useState } from "react" + +export default function Manager() { + const { setStatus } = useManagerGameStore() + const router = useRouter() + const { socket } = useSocket() + + const [isAuth, setIsAuth] = useState(false) + const [quizzList, setQuizzList] = useState([]) + + useEvent("manager:quizzList", (quizzList) => { + setIsAuth(true) + setQuizzList(quizzList) + }) + + useEvent("manager:gameCreated", ({ gameId, inviteCode }) => { + setStatus("SHOW_ROOM", { text: "Waiting for the players", inviteCode }) + router.push(`/game/manager/${gameId}`) + }) + + const handleAuth = (password: string) => { + socket?.emit("manager:auth", password) + } + const handleCreate = (quizzId: string) => { + console.log(quizzId) + socket?.emit("game:create", quizzId) + console.log("create room") + } + + if (!isAuth) { + return + } + + return +} diff --git a/packages/web/src/app/(auth)/page.tsx b/packages/web/src/app/(auth)/page.tsx new file mode 100644 index 0000000..b4dff88 --- /dev/null +++ b/packages/web/src/app/(auth)/page.tsx @@ -0,0 +1,38 @@ +"use client" + +import logo from "@rahoot/web/assets/logo.svg" +import Room from "@rahoot/web/components/game/join/Room" +import Username from "@rahoot/web/components/game/join/Username" +import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" +import { usePlayerStore } from "@rahoot/web/stores/player" +import Image from "next/image" +import { useEffect } from "react" +import toast from "react-hot-toast" + +export default function Home() { + const { isConnected, connect } = useSocket() + const { player } = usePlayerStore() + + useEffect(() => { + if (!isConnected) { + connect() + } + }, [connect, isConnected]) + + useEvent("game:errorMessage", (message) => { + toast.error(message) + }) + + return ( +
+
+
+
+
+ + logo + + {!player ? : } +
+ ) +} diff --git a/packages/web/src/app/game/[gameId]/page.tsx b/packages/web/src/app/game/[gameId]/page.tsx new file mode 100644 index 0000000..ad6907e --- /dev/null +++ b/packages/web/src/app/game/[gameId]/page.tsx @@ -0,0 +1,78 @@ +"use client" + +import { Status } from "@rahoot/common/types/game/status" +import GameWrapper from "@rahoot/web/components/game/GameWrapper" +import Answers from "@rahoot/web/components/game/states/Answers" +import Prepared from "@rahoot/web/components/game/states/Prepared" +import Question from "@rahoot/web/components/game/states/Question" +import Result from "@rahoot/web/components/game/states/Result" +import Start from "@rahoot/web/components/game/states/Start" +import Wait from "@rahoot/web/components/game/states/Wait" +import { useEvent } from "@rahoot/web/contexts/socketProvider" +import { usePlayerGameStore } from "@rahoot/web/stores/game" +import { usePlayerStore } from "@rahoot/web/stores/player" +import { GAME_STATE_COMPONENTS } from "@rahoot/web/utils/constants" +import { useRouter } from "next/navigation" +import { useEffect } from "react" +import toast from "react-hot-toast" + +export default function Game() { + const router = useRouter() + const { player, logout } = usePlayerStore() + const { status, setStatus, resetStatus } = usePlayerGameStore() + + useEffect(() => { + if (!player) { + router.replace("/") + } + }, [player, router]) + + useEvent("game:status", ({ name, data }) => { + if (name in GAME_STATE_COMPONENTS) { + setStatus(name, data) + } + }) + + useEvent("game:reset", () => { + router.replace("/") + logout() + resetStatus() + toast("The game has been reset by the host") + }) + + let component = null + + switch (status.name) { + case Status.WAIT: + component = + + break + + case Status.SHOW_START: + component = + + break + + case Status.SHOW_PREPARED: + component = + + break + + case Status.SHOW_QUESTION: + component = + + break + + case Status.SHOW_RESULT: + component = + + break + + case Status.SELECT_ANSWER: + component = + + break + } + + return {component} +} diff --git a/packages/web/src/app/game/layout.tsx b/packages/web/src/app/game/layout.tsx new file mode 100644 index 0000000..7d4854a --- /dev/null +++ b/packages/web/src/app/game/layout.tsx @@ -0,0 +1,17 @@ +"use client" + +import { useSocket } from "@rahoot/web/contexts/socketProvider" +import { PropsWithChildren, useEffect } from "react" + +const GameLayout = ({ children }: PropsWithChildren) => { + const { isConnected, connect } = useSocket() + useEffect(() => { + if (!isConnected) { + connect() + } + }, [connect, isConnected]) + + return children +} + +export default GameLayout diff --git a/packages/web/src/app/game/manager/[gameId]/page.tsx b/packages/web/src/app/game/manager/[gameId]/page.tsx new file mode 100644 index 0000000..7d457d8 --- /dev/null +++ b/packages/web/src/app/game/manager/[gameId]/page.tsx @@ -0,0 +1,112 @@ +"use client" + +import { Status } from "@rahoot/common/types/game/status" +import GameWrapper from "@rahoot/web/components/game/GameWrapper" +import Answers from "@rahoot/web/components/game/states/Answers" +import Leaderboard from "@rahoot/web/components/game/states/Leaderboard" +import Podium from "@rahoot/web/components/game/states/Podium" +import Prepared from "@rahoot/web/components/game/states/Prepared" +import Question from "@rahoot/web/components/game/states/Question" +import Responses from "@rahoot/web/components/game/states/Responses" +import Room from "@rahoot/web/components/game/states/Room" +import Start from "@rahoot/web/components/game/states/Start" +import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" +import { useManagerGameStore } from "@rahoot/web/stores/game" +import { GAME_STATE_COMPONENTS_MANAGER } from "@rahoot/web/utils/constants" +import { useParams } from "next/navigation" +import { useEffect, useState } from "react" + +export default function ManagerGame() { + const { socket } = useSocket() + const [nextText, setNextText] = useState("Start") + const { status, setStatus } = useManagerGameStore() + const { gameId }: { gameId?: string } = useParams() + + useEvent("game:status", ({ name, data }) => { + if (name in GAME_STATE_COMPONENTS_MANAGER) { + setStatus(name, data) + } + }) + + useEffect(() => { + if (status.name === "SHOW_START") { + setNextText("Start") + } + }, [status.name]) + + const handleSkip = () => { + setNextText("Skip") + + switch (status.name) { + case Status.SHOW_ROOM: + socket?.emit("manager:startGame", { gameId }) + + break + + case Status.SELECT_ANSWER: + socket?.emit("manager:abortQuiz", { gameId }) + + break + + case Status.SHOW_RESPONSES: + socket?.emit("manager:showLeaderboard", { gameId }) + + break + + case Status.SHOW_LEADERBOARD: + socket?.emit("manager:nextQuestion", { gameId }) + + break + } + } + + let component = null + + switch (status.name) { + case Status.SHOW_ROOM: + component = + + break + + case Status.SHOW_START: + component = + + break + + case Status.SHOW_PREPARED: + component = + + break + + case Status.SHOW_QUESTION: + component = + + break + + case Status.SELECT_ANSWER: + component = + + break + + case Status.SHOW_RESPONSES: + component = + + break + + case Status.SHOW_LEADERBOARD: + component = + + break + + case Status.FINISHED: + component = + + break + } + + return ( + + {component} + + ) +} diff --git a/src/styles/globals.css b/packages/web/src/app/globals.css similarity index 96% rename from src/styles/globals.css rename to packages/web/src/app/globals.css index ee0bcf6..c7b2bcf 100644 --- a/src/styles/globals.css +++ b/packages/web/src/app/globals.css @@ -1,6 +1,9 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss"; + +@theme { + --color-primary: #ff9900; + --color-secondary: #1a140b; +} .btn-shadow { box-shadow: rgba(0, 0, 0, 0.25) 0px -4px inset; diff --git a/packages/web/src/app/layout.tsx b/packages/web/src/app/layout.tsx new file mode 100644 index 0000000..99c9970 --- /dev/null +++ b/packages/web/src/app/layout.tsx @@ -0,0 +1,29 @@ +import Toaster from "@rahoot/web/components/Toaster" +import { SocketProvider } from "@rahoot/web/contexts/socketProvider" +import type { Metadata } from "next" +import { Montserrat } from "next/font/google" +import { PropsWithChildren } from "react" +import "./globals.css" + +const montserrat = Montserrat({ + variable: "--font-montserrat", + subsets: ["latin"], +}) + +export const metadata: Metadata = { + title: "Rahoot !", + icons: "/icon.svg", +} + +export default function RootLayout({ children }: PropsWithChildren) { + return ( + + + +
{children}
+ +
+ + + ) +} diff --git a/packages/web/src/app/socket/route.ts b/packages/web/src/app/socket/route.ts new file mode 100644 index 0000000..a98586b --- /dev/null +++ b/packages/web/src/app/socket/route.ts @@ -0,0 +1,10 @@ +import env from "@rahoot/web/env" +import { NextResponse } from "next/server" + +export function GET() { + return NextResponse.json({ + url: env.SOCKET_URL, + }) +} + +export const dynamic = "force-dynamic" diff --git a/src/assets/background.webp b/packages/web/src/assets/background.webp similarity index 100% rename from src/assets/background.webp rename to packages/web/src/assets/background.webp diff --git a/src/assets/loader.svg b/packages/web/src/assets/loader.svg similarity index 100% rename from src/assets/loader.svg rename to packages/web/src/assets/loader.svg diff --git a/src/assets/logo.svg b/packages/web/src/assets/logo.svg similarity index 100% rename from src/assets/logo.svg rename to packages/web/src/assets/logo.svg diff --git a/src/components/AnswerButton.jsx b/packages/web/src/components/AnswerButton.tsx similarity index 67% rename from src/components/AnswerButton.jsx rename to packages/web/src/components/AnswerButton.tsx index 3981737..9706e84 100644 --- a/src/components/AnswerButton.jsx +++ b/packages/web/src/components/AnswerButton.tsx @@ -1,11 +1,17 @@ import clsx from "clsx" +import { ButtonHTMLAttributes, ElementType, PropsWithChildren } from "react" + +type Props = PropsWithChildren & + ButtonHTMLAttributes & { + icon: ElementType + } export default function AnswerButton({ className, icon: Icon, children, ...otherProps -}) { +}: Props) { return ( + )} + + + {children} + + {!manager && ( +
+

{player?.username}

+
+ {player?.points} +
+
+ )} + + ) +} diff --git a/packages/web/src/components/game/create/ManagerPassword.tsx b/packages/web/src/components/game/create/ManagerPassword.tsx new file mode 100644 index 0000000..524f06a --- /dev/null +++ b/packages/web/src/components/game/create/ManagerPassword.tsx @@ -0,0 +1,52 @@ +import logo from "@rahoot/web/assets/logo.svg" +import Button from "@rahoot/web/components/Button" +import Form from "@rahoot/web/components/Form" +import Input from "@rahoot/web/components/Input" +import { useEvent } from "@rahoot/web/contexts/socketProvider" +import Image from "next/image" +import { KeyboardEvent, useState } from "react" +import toast from "react-hot-toast" + +type Props = { + // eslint-disable-next-line no-unused-vars + onSubmit: (password: string) => void +} + +export default function ManagerPassword({ onSubmit }: Props) { + const [password, setPassword] = useState("") + + const handleSubmit = () => { + onSubmit(password) + } + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Enter") { + handleSubmit() + } + } + + useEvent("manager:errorMessage", (message) => { + toast.error(message) + }) + + return ( +
+
+
+
+
+ + logo + +
+ setPassword(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="Manager password" + /> + +
+
+ ) +} diff --git a/packages/web/src/components/game/create/SelectQuizz.tsx b/packages/web/src/components/game/create/SelectQuizz.tsx new file mode 100644 index 0000000..d4b0d5b --- /dev/null +++ b/packages/web/src/components/game/create/SelectQuizz.tsx @@ -0,0 +1,79 @@ +import { Quizz } from "@rahoot/common/types/game" +import logo from "@rahoot/web/assets/logo.svg" +import Button from "@rahoot/web/components/Button" +import clsx from "clsx" +import Image from "next/image" +import { useState } from "react" +import toast from "react-hot-toast" + +type QuizzWithId = Quizz & { id: string } + +type Props = { + quizzList: QuizzWithId[] + // eslint-disable-next-line no-unused-vars + onSelect: (id: string) => void +} + +export default function SelectQuizz({ quizzList, onSelect }: Props) { + const [selected, setSelected] = useState(null) + + const handleSelect = (id: string) => () => { + if (selected === id) { + setSelected(null) + } else { + setSelected(id) + } + } + + const handleSubmit = () => { + if (!selected) { + toast.error("Please select a quizz") + + return + } + + onSelect(selected) + } + + return ( +
+
+
+
+
+ + logo + +
+
+

Select a quizz

+
+ {quizzList.map((quizz) => ( + + ))} +
+
+ +
+
+ ) +} diff --git a/packages/web/src/components/game/join/Room.tsx b/packages/web/src/components/game/join/Room.tsx new file mode 100644 index 0000000..2a9af6d --- /dev/null +++ b/packages/web/src/components/game/join/Room.tsx @@ -0,0 +1,37 @@ +import Button from "@rahoot/web/components/Button" +import Form from "@rahoot/web/components/Form" +import Input from "@rahoot/web/components/Input" +import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" +import { usePlayerStore } from "@rahoot/web/stores/player" +import { KeyboardEvent, useState } from "react" + +export default function Room() { + const { socket } = useSocket() + const { join } = usePlayerStore() + const [invitation, setInvitation] = useState("") + + const handleJoin = () => { + socket?.emit("player:join", invitation) + } + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Enter") { + handleJoin() + } + } + + useEvent("game:successRoom", (gameId) => { + join(gameId) + }) + + return ( +
+ setInvitation(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="PIN Code here" + /> + +
+ ) +} diff --git a/packages/web/src/components/game/join/Username.tsx b/packages/web/src/components/game/join/Username.tsx new file mode 100644 index 0000000..9425c19 --- /dev/null +++ b/packages/web/src/components/game/join/Username.tsx @@ -0,0 +1,44 @@ +"use client" + +import Button from "@rahoot/web/components/Button" +import Form from "@rahoot/web/components/Form" +import Input from "@rahoot/web/components/Input" +import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" +import { usePlayerStore } from "@rahoot/web/stores/player" + +import { useRouter } from "next/navigation" +import { KeyboardEvent, useState } from "react" + +export default function Username() { + const { socket } = useSocket() + const { player, login } = usePlayerStore() + const router = useRouter() + const [username, setUsername] = useState("") + + const handleLogin = () => { + socket?.emit("player:login", { gameId: player?.gameId, data: { username } }) + } + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Enter") { + handleLogin() + } + } + + useEvent("game:successJoin", (gameId) => { + login(username) + + router.replace(`/game/${gameId}`) + }) + + return ( +
+ setUsername(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="Username here" + /> + +
+ ) +} diff --git a/packages/web/src/components/game/states/Answers.tsx b/packages/web/src/components/game/states/Answers.tsx new file mode 100644 index 0000000..f906c99 --- /dev/null +++ b/packages/web/src/components/game/states/Answers.tsx @@ -0,0 +1,114 @@ +"use client" + +import { CommonStatusDataMap } from "@rahoot/common/types/game/status" +import AnswerButton from "@rahoot/web/components/AnswerButton" +import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" +import { usePlayerStore } from "@rahoot/web/stores/player" +import { + ANSWERS_COLORS, + ANSWERS_ICONS, + SFX_ANSWERS_MUSIC, + SFX_ANSWERS_SOUND, +} from "@rahoot/web/utils/constants" +import clsx from "clsx" +import { useParams } from "next/navigation" +import { useEffect, useState } from "react" +import useSound from "use-sound" + +type Props = { + data: CommonStatusDataMap["SELECT_ANSWER"] +} + +export default function Answers({ + data: { question, answers, image, time, totalPlayer }, +}: Props) { + const { gameId }: { gameId?: string } = useParams() + const { socket } = useSocket() + const { player } = usePlayerStore() + + const [cooldown, setCooldown] = useState(time) + const [totalAnswer, setTotalAnswer] = useState(0) + + const [sfxPop] = useSound(SFX_ANSWERS_SOUND, { + volume: 0.1, + }) + + const [playMusic] = useSound(SFX_ANSWERS_MUSIC, { + volume: 0.2, + interrupt: true, + }) + + const handleAnswer = (answerKey: number) => () => { + if (!player) { + return + } + + socket?.emit("player:selectedAnswer", { + gameId, + data: { + answerKey, + }, + }) + sfxPop() + } + + useEffect(() => { + console.log("play music") + playMusic() + }, []) + + useEvent("game:cooldown", (sec) => { + setCooldown(sec) + }) + + useEvent("game:playerAnswer", (count) => { + setTotalAnswer(count) + sfxPop() + }) + + return ( +
+
+

+ {question} +

+ + {Boolean(image) && ( + {question} + )} +
+ +
+
+
+ Time + {cooldown} +
+
+ Answers + + {totalAnswer}/{totalPlayer} + +
+
+ +
+ {answers.map((answer, key) => ( + + {answer} + + ))} +
+
+
+ ) +} diff --git a/src/components/game/states/Leaderboard.jsx b/packages/web/src/components/game/states/Leaderboard.tsx similarity index 64% rename from src/components/game/states/Leaderboard.jsx rename to packages/web/src/components/game/states/Leaderboard.tsx index b87d959..cfa27a6 100644 --- a/src/components/game/states/Leaderboard.jsx +++ b/packages/web/src/components/game/states/Leaderboard.tsx @@ -1,4 +1,10 @@ -export default function Leaderboard({ data: { leaderboard } }) { +import { ManagerStatusDataMap } from "@rahoot/common/types/game/status" + +type Props = { + data: ManagerStatusDataMap["SHOW_LEADERBOARD"] +} + +export default function Leaderboard({ data: { leaderboard } }: Props) { return (

@@ -8,7 +14,7 @@ export default function Leaderboard({ data: { leaderboard } }) { {leaderboard.map(({ username, points }, key) => (
{username} {points} diff --git a/src/components/game/states/Podium.jsx b/packages/web/src/components/game/states/Podium.tsx similarity index 76% rename from src/components/game/states/Podium.jsx rename to packages/web/src/components/game/states/Podium.tsx index 839481d..7e4ed7c 100644 --- a/src/components/game/states/Podium.jsx +++ b/packages/web/src/components/game/states/Podium.tsx @@ -1,16 +1,23 @@ +"use client" + +import { ManagerStatusDataMap } from "@rahoot/common/types/game/status" +import useScreenSize from "@rahoot/web/hook/useScreenSize" import { SFX_PODIUM_FIRST, SFX_PODIUM_SECOND, SFX_PODIUM_THREE, SFX_SNEAR_ROOL, -} from "@/constants" -import useScreenSize from "@/hook/useScreenSize" +} from "@rahoot/web/utils/constants" import clsx from "clsx" import { useEffect, useState } from "react" import ReactConfetti from "react-confetti" import useSound from "use-sound" -export default function Podium({ data: { subject, top } }) { +type Props = { + data: ManagerStatusDataMap["FINISHED"] +} + +export default function Podium({ data: { subject, top } }: Props) { const [apparition, setApparition] = useState(0) const { width, height } = useScreenSize() @@ -56,7 +63,7 @@ export default function Podium({ data: { subject, top } }) { break } - }, [apparition, sfxFirst, sfxSecond, sfxtThree, sfxRool]) + }, [apparition, sfxFirst, sfxSecond, sfxtThree, sfxRool, sfxRoolStop]) useEffect(() => { if (top.length < 3) { @@ -77,7 +84,7 @@ export default function Podium({ data: { subject, top } }) { // eslint-disable-next-line consistent-return return () => clearInterval(interval) - }, [apparition]) + }, [apparition, top.length]) return ( <> @@ -90,8 +97,8 @@ export default function Podium({ data: { subject, top } }) { )} {apparition >= 3 && top.length >= 3 && ( -
-
{" "} +
+
)}
@@ -100,7 +107,8 @@ export default function Podium({ data: { subject, top } }) {

{top[1] && (

= 4, }, @@ -119,7 +127,7 @@ export default function Podium({ data: { subject, top } }) { > {top[1].username}

-
+

2

@@ -143,13 +151,13 @@ export default function Podium({ data: { subject, top } }) { >

= 4 }, )} > {top[0].username}

-
+

1

@@ -170,7 +178,7 @@ export default function Podium({ data: { subject, top } }) { >

= 4, }, @@ -178,7 +186,7 @@ export default function Podium({ data: { subject, top } }) { > {top[2].username}

-
+

3

diff --git a/src/components/game/states/Prepared.jsx b/packages/web/src/components/game/states/Prepared.tsx similarity index 75% rename from src/components/game/states/Prepared.jsx rename to packages/web/src/components/game/states/Prepared.tsx index 4862f5c..1053e12 100644 --- a/src/components/game/states/Prepared.jsx +++ b/packages/web/src/components/game/states/Prepared.tsx @@ -1,8 +1,15 @@ -import { ANSWERS_COLORS, ANSWERS_ICONS } from "@/constants" +import { CommonStatusDataMap } from "@rahoot/common/types/game/status" +import { ANSWERS_COLORS, ANSWERS_ICONS } from "@rahoot/web/utils/constants" import clsx from "clsx" import { createElement } from "react" -export default function Prepared({ data: { totalAnswers, questionNumber } }) { +type Props = { + data: CommonStatusDataMap["SHOW_PREPARED"] +} + +export default function Prepared({ + data: { totalAnswers, questionNumber }, +}: Props) { return (

diff --git a/src/components/game/states/Question.jsx b/packages/web/src/components/game/states/Question.tsx similarity index 68% rename from src/components/game/states/Question.jsx rename to packages/web/src/components/game/states/Question.tsx index 4721be1..2c1ea90 100644 --- a/src/components/game/states/Question.jsx +++ b/packages/web/src/components/game/states/Question.tsx @@ -1,8 +1,17 @@ -import { SFX_SHOW_SOUND } from "@/constants" +"use client" + +import { CommonStatusDataMap } from "@rahoot/common/types/game/status" +import { SFX_SHOW_SOUND } from "@rahoot/web/utils/constants" import { useEffect } from "react" import useSound from "use-sound" -export default function Question({ data: { question, image, cooldown } }) { +type Props = { + data: CommonStatusDataMap["SHOW_QUESTION"] +} + +export default function Question({ + data: { question, image, cooldown }, +}: Props) { const [sfxShow] = useSound(SFX_SHOW_SOUND, { volume: 0.5 }) useEffect(() => { @@ -25,7 +34,7 @@ export default function Question({ data: { question, image, cooldown } }) { )}

diff --git a/packages/web/src/components/game/states/Responses.tsx b/packages/web/src/components/game/states/Responses.tsx new file mode 100644 index 0000000..c16156f --- /dev/null +++ b/packages/web/src/components/game/states/Responses.tsx @@ -0,0 +1,125 @@ +"use client" + +import { ManagerStatusDataMap } from "@rahoot/common/types/game/status" +import { + ANSWERS_COLORS, + ANSWERS_ICONS, + SFX_ANSWERS_MUSIC, + SFX_RESULTS_SOUND, +} from "@rahoot/web/utils/constants" +import clsx from "clsx" +import { useEffect, useState } from "react" +import useSound from "use-sound" +import AnswerButton from "../../AnswerButton" + +const calculatePercentages = ( + objectResponses: Record, +): Record => { + const keys = Object.keys(objectResponses) + const values = Object.values(objectResponses) + + if (!values.length) { + return {} + } + + const totalSum = values.reduce( + (accumulator, currentValue) => accumulator + currentValue, + 0, + ) + + const result: Record = {} + + keys.forEach((key) => { + result[key] = `${((objectResponses[key] / totalSum) * 100).toFixed()}%` + }) + + return result +} + +type Props = { + data: ManagerStatusDataMap["SHOW_RESPONSES"] +} + +export default function Responses({ + data: { question, answers, responses, correct }, +}: Props) { + const [percentages, setPercentages] = useState>({}) + const [isMusicPlaying, setIsMusicPlaying] = useState(false) + + const [sfxResults] = useSound(SFX_RESULTS_SOUND, { + volume: 0.2, + }) + + const [playMusic, { stop: stopMusic }] = useSound(SFX_ANSWERS_MUSIC, { + volume: 0.2, + onplay: () => { + setIsMusicPlaying(true) + }, + onend: () => { + setIsMusicPlaying(false) + }, + }) + + useEffect(() => { + stopMusic() + sfxResults() + + setPercentages(calculatePercentages(responses)) + }, [responses, playMusic, stopMusic, sfxResults]) + + useEffect(() => { + if (!isMusicPlaying) { + playMusic() + } + }, [isMusicPlaying, playMusic]) + + useEffect(() => { + stopMusic() + }, [playMusic, stopMusic]) + + return ( +
+
+

+ {question} +

+ +
+ {answers.map((_, key) => ( +
+ + {responses[key] || 0} + +
+ ))} +
+
+ +
+
+ {answers.map((answer, key) => ( + + {answer} + + ))} +
+
+
+ ) +} diff --git a/src/components/game/states/Result.jsx b/packages/web/src/components/game/states/Result.tsx similarity index 64% rename from src/components/game/states/Result.jsx rename to packages/web/src/components/game/states/Result.tsx index 49ff7cb..357fa81 100644 --- a/src/components/game/states/Result.jsx +++ b/packages/web/src/components/game/states/Result.tsx @@ -1,24 +1,28 @@ -import CricleCheck from "@/components/icons/CricleCheck" -import CricleXmark from "@/components/icons/CricleXmark" -import { SFX_RESULTS_SOUND } from "@/constants" -import { usePlayerContext } from "@/context/player" +"use client" + +import { CommonStatusDataMap } from "@rahoot/common/types/game/status" +import CricleCheck from "@rahoot/web/components/icons/CricleCheck" +import CricleXmark from "@rahoot/web/components/icons/CricleXmark" +import { usePlayerStore } from "@rahoot/web/stores/player" +import { SFX_RESULTS_SOUND } from "@rahoot/web/utils/constants" import { useEffect } from "react" import useSound from "use-sound" +type Props = { + data: CommonStatusDataMap["SHOW_RESULT"] +} + export default function Result({ data: { correct, message, points, myPoints, rank, aheadOfMe }, -}) { - const { dispatch } = usePlayerContext() +}: Props) { + const player = usePlayerStore() const [sfxResults] = useSound(SFX_RESULTS_SOUND, { volume: 0.2, }) useEffect(() => { - dispatch({ - type: "UPDATE", - payload: { points: myPoints }, - }) + player.updatePoints(myPoints) sfxResults() }, [sfxResults]) @@ -28,7 +32,7 @@ export default function Result({ {correct ? ( ) : ( - + )}

{message} diff --git a/packages/web/src/components/game/states/Room.tsx b/packages/web/src/components/game/states/Room.tsx new file mode 100644 index 0000000..0190347 --- /dev/null +++ b/packages/web/src/components/game/states/Room.tsx @@ -0,0 +1,70 @@ +"use client" + +import { Player } from "@rahoot/common/types/game" +import { ManagerStatusDataMap } from "@rahoot/common/types/game/status" +import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" +import { useState } from "react" + +type Props = { + data: ManagerStatusDataMap["SHOW_ROOM"] +} + +export default function Room({ data: { text, inviteCode } }: Props) { + const { socket } = useSocket() + const [playerList, setPlayerList] = useState([]) + const [totalPlayers, setTotalPlayers] = useState(0) + + useEvent("manager:newPlayer", (player) => { + setPlayerList([...playerList, player]) + }) + + useEvent("manager:removePlayer", (playerId) => { + setPlayerList(playerList.filter((p) => p.id !== playerId)) + }) + + useEvent("manager:playerKicked", (playerId) => { + setPlayerList(playerList.filter((p) => p.id !== playerId)) + }) + + useEvent("game:totalPlayers", (total) => { + setTotalPlayers(total) + }) + + const handleKick = (playerId: string) => () => { + socket?.emit("manager:kickPlayer", { + data: { playerId }, + }) + } + + return ( +
+
+ {inviteCode} +
+ +

+ {text} +

+ +
+ + Players Joined: {totalPlayers} + +
+ +
+ {playerList.map((player) => ( +
+ + {player.username} + +
+ ))} +
+
+ ) +} diff --git a/src/components/game/states/Start.jsx b/packages/web/src/components/game/states/Start.tsx similarity index 59% rename from src/components/game/states/Start.jsx rename to packages/web/src/components/game/states/Start.tsx index 19fe4df..a85ab01 100644 --- a/src/components/game/states/Start.jsx +++ b/packages/web/src/components/game/states/Start.tsx @@ -1,11 +1,17 @@ -import { SFX_BOUMP_SOUND } from "@/constants" -import { useSocketContext } from "@/context/socket" +"use client" + +import { CommonStatusDataMap } from "@rahoot/common/types/game/status" +import { useEvent } from "@rahoot/web/contexts/socketProvider" +import { SFX_BOUMP_SOUND } from "@rahoot/web/utils/constants" import clsx from "clsx" -import { useEffect, useState } from "react" +import { useState } from "react" import useSound from "use-sound" -export default function Start({ data: { time, subject } }) { - const { socket } = useSocketContext() +type Props = { + data: CommonStatusDataMap["SHOW_START"] +} + +export default function Start({ data: { time, subject } }: Props) { const [showTitle, setShowTitle] = useState(true) const [cooldown, setCooldown] = useState(time) @@ -13,22 +19,15 @@ export default function Start({ data: { time, subject } }) { volume: 0.2, }) - useEffect(() => { - socket.on("game:startCooldown", () => { - sfxBoump() - setShowTitle(false) - }) + useEvent("game:startCooldown", () => { + sfxBoump() + setShowTitle(false) + }) - socket.on("game:cooldown", (sec) => { - sfxBoump() - setCooldown(sec) - }) - - return () => { - socket.off("game:startCooldown") - socket.off("game:cooldown") - } - }, [sfxBoump]) + useEvent("game:cooldown", (sec) => { + sfxBoump() + setCooldown(sec) + }) return (
@@ -40,7 +39,7 @@ export default function Start({ data: { time, subject } }) { <>
diff --git a/src/components/icons/Circle.jsx b/packages/web/src/components/icons/Circle.tsx similarity index 86% rename from src/components/icons/Circle.jsx rename to packages/web/src/components/icons/Circle.tsx index 2393c78..4925030 100644 --- a/src/components/icons/Circle.jsx +++ b/packages/web/src/components/icons/Circle.tsx @@ -1,4 +1,9 @@ -export default function Circle({ className, fill = "#FFF" }) { +type Props = { + className?: string + fill?: string +} + +export default function Circle({ className, fill = "#FFF" }: Props) { return ( diff --git a/src/components/icons/CricleXmark.jsx b/packages/web/src/components/icons/CricleXmark.tsx similarity index 92% rename from src/components/icons/CricleXmark.jsx rename to packages/web/src/components/icons/CricleXmark.tsx index fb7d0e0..144a28b 100644 --- a/src/components/icons/CricleXmark.jsx +++ b/packages/web/src/components/icons/CricleXmark.tsx @@ -1,4 +1,8 @@ -export default function CricleXmark({ className }) { +type Props = { + className?: string +} + +export default function CricleXmark({ className }: Props) { return ( diff --git a/src/components/icons/Pentagon.jsx b/packages/web/src/components/icons/Pentagon.tsx similarity index 89% rename from src/components/icons/Pentagon.jsx rename to packages/web/src/components/icons/Pentagon.tsx index f5eb3c8..d734871 100644 --- a/src/components/icons/Pentagon.jsx +++ b/packages/web/src/components/icons/Pentagon.tsx @@ -1,4 +1,10 @@ -export default function Pentagon({ className, fill, stroke }) { +type Props = { + className?: string + fill?: string + stroke?: string +} + +export default function Pentagon({ className, fill, stroke }: Props) { return ( + +interface SocketContextValue { + socket: TypedSocket | null + isConnected: boolean + connect: () => void + disconnect: () => void + reconnect: () => void +} + +const SocketContext = createContext({ + socket: null, + isConnected: false, + connect: () => {}, + disconnect: () => {}, + reconnect: () => {}, +}) + +const getSocketServer = async () => { + const res = await ky.get("/socket").json<{ url: string }>() + + return res.url +} + +export const SocketProvider = ({ children }: { children: React.ReactNode }) => { + const [socket, setSocket] = useState(null) + const [isConnected, setIsConnected] = useState(false) + + useEffect(() => { + let s: TypedSocket | null = null + + const initSocket = async () => { + try { + const socketUrl = await getSocketServer() + + s = io(socketUrl, { + transports: ["websocket"], + autoConnect: false, + }) + + setSocket(s) + + s.on("connect", () => { + setIsConnected(true) + }) + + s.on("disconnect", () => { + console.log("Socket disconnected") + setIsConnected(false) + }) + + s.on("connect_error", (err) => { + console.error("Connection error:", err.message) + }) + } catch (error) { + console.error("Failed to initialize socket:", error) + } + } + + initSocket() + + return () => { + s?.disconnect() + } + }, []) + + const connect = useCallback(() => { + if (socket && !socket.connected) { + console.log("🔌 Manual connect") + socket.connect() + } + }, [socket]) + + const disconnect = useCallback(() => { + if (socket && socket.connected) { + console.log("🧹 Manual disconnect") + socket.disconnect() + } + }, [socket]) + + const reconnect = useCallback(() => { + if (socket) { + console.log("♻️ Manual reconnect") + socket.disconnect() + socket.connect() + } + }, [socket]) + + return ( + + {children} + + ) +} + +export const useSocket = () => useContext(SocketContext) + +export const useEvent = ( + event: E, + callback: ServerToClientEvents[E], +) => { + const { socket } = useSocket() + + useEffect(() => { + if (!socket) { + return + } + + socket.on(event, callback as any) + + // eslint-disable-next-line consistent-return + return () => { + socket.off(event, callback as any) + } + }, [socket, event, callback]) +} diff --git a/packages/web/src/env.ts b/packages/web/src/env.ts new file mode 100644 index 0000000..d5337cf --- /dev/null +++ b/packages/web/src/env.ts @@ -0,0 +1,14 @@ +import { createEnv } from "@t3-oss/env-nextjs" +import { z } from "zod" + +const env = createEnv({ + server: { + SOCKET_URL: z.string().default("http://localhost:3001"), + }, + + runtimeEnv: { + SOCKET_URL: process.env.SOCKET_URL, + }, +}) + +export default env diff --git a/src/hook/useScreenSize.js b/packages/web/src/hook/useScreenSize.ts similarity index 100% rename from src/hook/useScreenSize.js rename to packages/web/src/hook/useScreenSize.ts diff --git a/packages/web/src/stores/game.tsx b/packages/web/src/stores/game.tsx new file mode 100644 index 0000000..2d22aac --- /dev/null +++ b/packages/web/src/stores/game.tsx @@ -0,0 +1,44 @@ +import { StatusDataMap } from "@rahoot/common/types/game/status" +import { create } from "zustand" + +export type Status = { + [K in keyof T]: { name: K; data: T[K] } +}[keyof T] + +export function createStatus( + name: K, + data: T[K], +): Status { + return { name, data } +} + +type GameStore = { + status: Status + // eslint-disable-next-line no-unused-vars + setStatus: (name: K, data: T[K]) => void + resetStatus: () => void +} + +export const usePlayerGameStore = create>((set) => { + const initialStatus = createStatus("WAIT", { + text: "Waiting for the players", + }) + + return { + status: initialStatus, + setStatus: (name, data) => set({ status: createStatus(name, data) }), + resetStatus: () => set({ status: initialStatus }), + } +}) + +export const useManagerGameStore = create>((set) => { + const initialStatus = createStatus("SHOW_ROOM", { + text: "Waiting for the players", + }) + + return { + status: initialStatus, + setStatus: (name, data) => set({ status: createStatus(name, data) }), + resetStatus: () => set({ status: initialStatus }), + } +}) diff --git a/packages/web/src/stores/player.tsx b/packages/web/src/stores/player.tsx new file mode 100644 index 0000000..9f9b046 --- /dev/null +++ b/packages/web/src/stores/player.tsx @@ -0,0 +1,37 @@ +/* eslint-disable no-unused-vars */ +import { create } from "zustand" + +type PlayerState = { + gameId?: string + username?: string + points?: number +} + +type PlayerStore = { + player: PlayerState | null + login: (gameId: string) => void + join: (username: string) => void + updatePoints: (points: number) => void + logout: () => void +} + +export const usePlayerStore = create((set) => ({ + player: null, + + login: (username) => + set((state) => ({ + player: { ...state.player, username }, + })), + + join: (gameId) => + set((state) => ({ + player: { ...state.player, gameId, points: 0 }, + })), + + updatePoints: (points) => + set((state) => ({ + player: { ...state.player, points }, + })), + + logout: () => set({ player: null }), +})) diff --git a/packages/web/src/utils/constants.ts b/packages/web/src/utils/constants.ts new file mode 100644 index 0000000..ee5c04f --- /dev/null +++ b/packages/web/src/utils/constants.ts @@ -0,0 +1,63 @@ +import Answers from "@rahoot/web/components/game/states/Answers" +import Leaderboard from "@rahoot/web/components/game/states/Leaderboard" +import Podium from "@rahoot/web/components/game/states/Podium" +import Prepared from "@rahoot/web/components/game/states/Prepared" +import Question from "@rahoot/web/components/game/states/Question" +import Responses from "@rahoot/web/components/game/states/Responses" +import Result from "@rahoot/web/components/game/states/Result" +import Room from "@rahoot/web/components/game/states/Room" +import Start from "@rahoot/web/components/game/states/Start" +import Wait from "@rahoot/web/components/game/states/Wait" + +import { Status } from "@rahoot/common/types/game/status" +import Circle from "@rahoot/web/components/icons/Circle" +import Rhombus from "@rahoot/web/components/icons/Rhombus" +import Square from "@rahoot/web/components/icons/Square" +import Triangle from "@rahoot/web/components/icons/Triangle" + +export const ANSWERS_COLORS = [ + "bg-red-500", + "bg-blue-500", + "bg-yellow-500", + "bg-green-500", +] + +export const ANSWERS_ICONS = [Triangle, Rhombus, Circle, Square] + +export const GAME_STATES = { + status: { + name: Status.WAIT, + data: { text: "Waiting for the players" }, + }, + question: { + current: 1, + total: null, + }, +} + +export const GAME_STATE_COMPONENTS = { + [Status.SELECT_ANSWER]: Answers, + [Status.SHOW_QUESTION]: Question, + [Status.WAIT]: Wait, + [Status.SHOW_START]: Start, + [Status.SHOW_RESULT]: Result, + [Status.SHOW_PREPARED]: Prepared, +} + +export const GAME_STATE_COMPONENTS_MANAGER = { + ...GAME_STATE_COMPONENTS, + [Status.SHOW_ROOM]: Room, + [Status.SHOW_RESPONSES]: Responses, + [Status.SHOW_LEADERBOARD]: Leaderboard, + [Status.FINISHED]: Podium, +} + +export const SFX_ANSWERS_MUSIC = "/sounds/answersMusic.mp3" +export const SFX_ANSWERS_SOUND = "/sounds/answersSound.mp3" +export const SFX_RESULTS_SOUND = "/sounds/results.mp3" +export const SFX_SHOW_SOUND = "/sounds/show.mp3" +export const SFX_BOUMP_SOUND = "/sounds/boump.mp3" +export const SFX_PODIUM_THREE = "/sounds/three.mp3" +export const SFX_PODIUM_SECOND = "/sounds/second.mp3" +export const SFX_PODIUM_FIRST = "/sounds/first.mp3" +export const SFX_SNEAR_ROOL = "/sounds/snearRoll.mp3" diff --git a/packages/web/tsconfig.json b/packages/web/tsconfig.json new file mode 100644 index 0000000..cbf9110 --- /dev/null +++ b/packages/web/tsconfig.json @@ -0,0 +1,31 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + "next-env.d.ts", + "dist/types/**/*.ts" + ], + "exclude": ["node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..6804027 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,4911 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + dotenv-cli: + specifier: ^10.0.0 + version: 10.0.0 + typescript: + specifier: ^5.0.0 + version: 5.9.2 + + packages/common: + dependencies: + socket.io: + specifier: ^4.8.1 + version: 4.8.1 + zod: + specifier: ^3.22.4 + version: 3.25.76 + devDependencies: + '@types/node': + specifier: ^20.11.0 + version: 20.19.17 + typescript: + specifier: ^5.3.3 + version: 5.9.2 + + packages/socket: + dependencies: + '@rahoot/common': + specifier: workspace:* + version: link:../common + '@t3-oss/env-core': + specifier: ^0.13.8 + version: 0.13.8(typescript@5.9.2)(zod@4.1.11) + socket.io: + specifier: ^4.8.1 + version: 4.8.1 + uuid: + specifier: ^13.0.0 + version: 13.0.0 + zod: + specifier: ^4.1.11 + version: 4.1.11 + devDependencies: + esbuild: + specifier: ^0.25.10 + version: 0.25.10 + tsx: + specifier: ^4.20.6 + version: 4.20.6 + + packages/web: + dependencies: + '@rahoot/common': + specifier: workspace:* + version: link:../common + '@rahoot/socket': + specifier: workspace:* + version: link:../socket + '@t3-oss/env-nextjs': + specifier: ^0.13.8 + version: 0.13.8(typescript@5.9.2)(zod@4.1.12) + clsx: + specifier: ^2.1.1 + version: 2.1.1 + ky: + specifier: ^1.11.0 + version: 1.11.0 + next: + specifier: 15.5.4 + version: 15.5.4(@babel/core@7.28.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react: + specifier: 19.1.0 + version: 19.1.0 + react-confetti: + specifier: ^6.4.0 + version: 6.4.0(react@19.1.0) + react-dom: + specifier: 19.1.0 + version: 19.1.0(react@19.1.0) + react-hot-toast: + specifier: ^2.6.0 + version: 2.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + socket.io-client: + specifier: ^4.8.1 + version: 4.8.1 + use-sound: + specifier: ^5.0.0 + version: 5.0.0(react@19.1.0) + yup: + specifier: ^1.7.1 + version: 1.7.1 + zod: + specifier: ^4.1.12 + version: 4.1.12 + zustand: + specifier: ^5.0.8 + version: 5.0.8(@types/react@19.1.15)(react@19.1.0) + devDependencies: + '@eslint/eslintrc': + specifier: ^3 + version: 3.3.1 + '@tailwindcss/postcss': + specifier: ^4 + version: 4.1.13 + '@types/node': + specifier: ^20 + version: 20.19.17 + '@types/react': + specifier: ^19 + version: 19.1.15 + '@types/react-dom': + specifier: ^19 + version: 19.1.9(@types/react@19.1.15) + '@typescript-eslint/eslint-plugin': + specifier: ^8.45.0 + version: 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + '@typescript-eslint/parser': + specifier: ^8.45.0 + version: 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + eslint: + specifier: ^9 + version: 9.36.0(jiti@2.6.0) + eslint-config-next: + specifier: 15.5.4 + version: 15.5.4(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + eslint-plugin-react: + specifier: ^7.37.5 + version: 7.37.5(eslint@9.36.0(jiti@2.6.0)) + eslint-plugin-react-hooks: + specifier: ^6.1.1 + version: 6.1.1(eslint@9.36.0(jiti@2.6.0)) + globals: + specifier: ^16.4.0 + version: 16.4.0 + prettier: + specifier: ^3.6.2 + version: 3.6.2 + prettier-plugin-tailwindcss: + specifier: ^0.6.14 + version: 0.6.14(prettier@3.6.2) + tailwindcss: + specifier: ^4 + version: 4.1.13 + typescript: + specifier: ^5 + version: 5.9.2 + +packages: + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.4': + resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.4': + resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.3': + resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.4': + resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.4': + resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.4': + resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} + engines: {node: '>=6.9.0'} + + '@emnapi/core@1.5.0': + resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==} + + '@emnapi/runtime@1.5.0': + resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@esbuild/aix-ppc64@0.25.10': + resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.10': + resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.10': + resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.10': + resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.10': + resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.10': + resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.10': + resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.10': + resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.10': + resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.10': + resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.10': + resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.10': + resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.10': + resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.10': + resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.10': + resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.10': + resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.10': + resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.10': + resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.10': + resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.10': + resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.10': + resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.10': + resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.10': + resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.10': + resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.10': + resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.10': + resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.3.1': + resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.2': + resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.36.0': + resolution: {integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.3.5': + resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@img/colour@1.0.0': + resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.4': + resolution: {integrity: sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.4': + resolution: {integrity: sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.3': + resolution: {integrity: sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.3': + resolution: {integrity: sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.3': + resolution: {integrity: sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.2.3': + resolution: {integrity: sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.2.3': + resolution: {integrity: sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.2.3': + resolution: {integrity: sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.2.3': + resolution: {integrity: sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': + resolution: {integrity: sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.2.3': + resolution: {integrity: sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.4': + resolution: {integrity: sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.34.4': + resolution: {integrity: sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.34.4': + resolution: {integrity: sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.4': + resolution: {integrity: sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.34.4': + resolution: {integrity: sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.4': + resolution: {integrity: sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.4': + resolution: {integrity: sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.34.4': + resolution: {integrity: sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.4': + resolution: {integrity: sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.4': + resolution: {integrity: sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.4': + resolution: {integrity: sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + + '@next/env@15.5.4': + resolution: {integrity: sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==} + + '@next/eslint-plugin-next@15.5.4': + resolution: {integrity: sha512-SR1vhXNNg16T4zffhJ4TS7Xn7eq4NfKfcOsRwea7RIAHrjRpI9ALYbamqIJqkAhowLlERffiwk0FMvTLNdnVtw==} + + '@next/swc-darwin-arm64@15.5.4': + resolution: {integrity: sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@15.5.4': + resolution: {integrity: sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@15.5.4': + resolution: {integrity: sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-musl@15.5.4': + resolution: {integrity: sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-x64-gnu@15.5.4': + resolution: {integrity: sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-musl@15.5.4': + resolution: {integrity: sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-win32-arm64-msvc@15.5.4': + resolution: {integrity: sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-x64-msvc@15.5.4': + resolution: {integrity: sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nolyfill/is-core-module@1.0.39': + resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} + engines: {node: '>=12.4.0'} + + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + + '@rushstack/eslint-patch@1.12.0': + resolution: {integrity: sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==} + + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + + '@swc/helpers@0.5.15': + resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + + '@t3-oss/env-core@0.13.8': + resolution: {integrity: sha512-L1inmpzLQyYu4+Q1DyrXsGJYCXbtXjC4cICw1uAKv0ppYPQv656lhZPU91Qd1VS6SO/bou1/q5ufVzBGbNsUpw==} + peerDependencies: + arktype: ^2.1.0 + typescript: '>=5.0.0' + valibot: ^1.0.0-beta.7 || ^1.0.0 + zod: ^3.24.0 || ^4.0.0-beta.0 + peerDependenciesMeta: + arktype: + optional: true + typescript: + optional: true + valibot: + optional: true + zod: + optional: true + + '@t3-oss/env-nextjs@0.13.8': + resolution: {integrity: sha512-QmTLnsdQJ8BiQad2W2nvV6oUpH4oMZMqnFEjhVpzU0h3sI9hn8zb8crjWJ1Amq453mGZs6A4v4ihIeBFDOrLeQ==} + peerDependencies: + arktype: ^2.1.0 + typescript: '>=5.0.0' + valibot: ^1.0.0-beta.7 || ^1.0.0 + zod: ^3.24.0 || ^4.0.0-beta.0 + peerDependenciesMeta: + arktype: + optional: true + typescript: + optional: true + valibot: + optional: true + zod: + optional: true + + '@tailwindcss/node@4.1.13': + resolution: {integrity: sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==} + + '@tailwindcss/oxide-android-arm64@4.1.13': + resolution: {integrity: sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.13': + resolution: {integrity: sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.13': + resolution: {integrity: sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.13': + resolution: {integrity: sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13': + resolution: {integrity: sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.13': + resolution: {integrity: sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.13': + resolution: {integrity: sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.13': + resolution: {integrity: sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.1.13': + resolution: {integrity: sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.1.13': + resolution: {integrity: sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.13': + resolution: {integrity: sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.13': + resolution: {integrity: sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.13': + resolution: {integrity: sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==} + engines: {node: '>= 10'} + + '@tailwindcss/postcss@4.1.13': + resolution: {integrity: sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ==} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/cors@2.8.19': + resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/node@20.19.17': + resolution: {integrity: sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==} + + '@types/react-dom@19.1.9': + resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==} + peerDependencies: + '@types/react': ^19.0.0 + + '@types/react@19.1.15': + resolution: {integrity: sha512-+kLxJpaJzXybyDyFXYADyP1cznTO8HSuBpenGlnKOAkH4hyNINiywvXS/tGJhsrGGP/gM185RA3xpjY0Yg4erA==} + + '@typescript-eslint/eslint-plugin@8.45.0': + resolution: {integrity: sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.45.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.45.0': + resolution: {integrity: sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.45.0': + resolution: {integrity: sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.45.0': + resolution: {integrity: sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.45.0': + resolution: {integrity: sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.45.0': + resolution: {integrity: sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.45.0': + resolution: {integrity: sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.45.0': + resolution: {integrity: sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.45.0': + resolution: {integrity: sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.45.0': + resolution: {integrity: sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axe-core@4.10.3: + resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} + engines: {node: '>=4'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + + baseline-browser-mapping@2.8.12: + resolution: {integrity: sha512-vAPMQdnyKCBtkmQA6FMCBvU9qFIppS3nzyXnEM+Lo2IAhG4Mpjv9cCxMudhgV3YdNNJv6TNqXy97dfRVL2LmaQ==} + hasBin: true + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.26.3: + resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001745: + resolution: {integrity: sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==} + + caniuse-lite@1.0.30001747: + resolution: {integrity: sha512-mzFa2DGIhuc5490Nd/G31xN1pnBnYMadtkyTjefPI7wzypqgCEpeWu9bJr0OnDsyKrW75zA9ZAt7pbQFmwLsQg==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + detect-libc@2.1.1: + resolution: {integrity: sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==} + engines: {node: '>=8'} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + dotenv-cli@10.0.0: + resolution: {integrity: sha512-lnOnttzfrzkRx2echxJHQRB6vOAMSCzzZg79IxpC00tU42wZPuZkQxNNrrwVAxaQZIIh001l4PxVlCrBxngBzA==} + hasBin: true + + dotenv-expand@11.0.7: + resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} + engines: {node: '>=12'} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + + dotenv@17.2.3: + resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + electron-to-chromium@1.5.230: + resolution: {integrity: sha512-A6A6Fd3+gMdaed9wX83CvHYJb4UuapPD5X5SLq72VZJzxHSY0/LUweGXRWmQlh2ln7KV7iw7jnwXK7dlPoOnHQ==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + engine.io-client@6.6.3: + resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==} + + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + + engine.io@6.6.4: + resolution: {integrity: sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==} + engines: {node: '>=10.2.0'} + + enhanced-resolve@5.18.3: + resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} + engines: {node: '>=10.13.0'} + + es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} + engines: {node: '>= 0.4'} + + 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-iterator-helpers@1.2.1: + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + esbuild@0.25.10: + resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} + engines: {node: '>=18'} + hasBin: true + + 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'} + + eslint-config-next@15.5.4: + resolution: {integrity: sha512-BzgVVuT3kfJes8i2GHenC1SRJ+W3BTML11lAOYFOOPzrk2xp66jBOAGEFRw+3LkYCln5UzvFsLhojrshb5Zfaw==} + peerDependencies: + eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 + typescript: '>=3.3.1' + peerDependenciesMeta: + typescript: + optional: true + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-import-resolver-typescript@3.10.1: + resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + eslint-plugin-import-x: '*' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + + eslint-module-utils@2.12.1: + resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-import@2.32.0: + resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jsx-a11y@6.10.2: + resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + + eslint-plugin-react-hooks@5.2.0: + resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react-hooks@6.1.1: + resolution: {integrity: sha512-St9EKZzOAQF704nt2oJvAKZHjhrpg25ClQoaAlHmPZuajFldVLqRDW4VBNAS01NzeiQF0m0qhG1ZA807K6aVaQ==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.36.0: + resolution: {integrity: sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + goober@2.1.16: + resolution: {integrity: sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==} + peerDependencies: + csstype: ^3.0.10 + + 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==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + howler@2.2.4: + resolution: {integrity: sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-bun-module@2.0.0: + resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + + jiti@2.6.0: + resolution: {integrity: sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + ky@1.11.0: + resolution: {integrity: sha512-NEyo0ICpS0cqSuyoJFMCnHOZJILqXsKhIZlHJGDYaH8OB5IFrGzuBpEwyoMZG6gUKMPrazH30Ax5XKaujvD8ag==} + engines: {node: '>=18'} + + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + + language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-darwin-arm64@1.30.1: + resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.1: + resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.1: + resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.1: + resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.1: + resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.1: + resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.1: + resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.1: + resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.1: + resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.1: + resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.1: + resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} + engines: {node: '>= 12.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.19: + resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@3.1.0: + resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} + engines: {node: '>= 18'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + napi-postinstall@0.3.3: + resolution: {integrity: sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + next@15.5.4: + resolution: {integrity: sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==} + engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.51.1 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + + node-releases@2.0.23: + resolution: {integrity: sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-plugin-tailwindcss@0.6.14: + resolution: {integrity: sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==} + engines: {node: '>=14.21.3'} + peerDependencies: + '@ianvs/prettier-plugin-sort-imports': '*' + '@prettier/plugin-hermes': '*' + '@prettier/plugin-oxc': '*' + '@prettier/plugin-pug': '*' + '@shopify/prettier-plugin-liquid': '*' + '@trivago/prettier-plugin-sort-imports': '*' + '@zackad/prettier-plugin-twig': '*' + prettier: ^3.0 + prettier-plugin-astro: '*' + prettier-plugin-css-order: '*' + prettier-plugin-import-sort: '*' + prettier-plugin-jsdoc: '*' + prettier-plugin-marko: '*' + prettier-plugin-multiline-arrays: '*' + prettier-plugin-organize-attributes: '*' + prettier-plugin-organize-imports: '*' + prettier-plugin-sort-imports: '*' + prettier-plugin-style-order: '*' + prettier-plugin-svelte: '*' + peerDependenciesMeta: + '@ianvs/prettier-plugin-sort-imports': + optional: true + '@prettier/plugin-hermes': + optional: true + '@prettier/plugin-oxc': + optional: true + '@prettier/plugin-pug': + optional: true + '@shopify/prettier-plugin-liquid': + optional: true + '@trivago/prettier-plugin-sort-imports': + optional: true + '@zackad/prettier-plugin-twig': + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-css-order: + optional: true + prettier-plugin-import-sort: + optional: true + prettier-plugin-jsdoc: + optional: true + prettier-plugin-marko: + optional: true + prettier-plugin-multiline-arrays: + optional: true + prettier-plugin-organize-attributes: + optional: true + prettier-plugin-organize-imports: + optional: true + prettier-plugin-sort-imports: + optional: true + prettier-plugin-style-order: + optional: true + prettier-plugin-svelte: + optional: true + + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-confetti@6.4.0: + resolution: {integrity: sha512-5MdGUcqxrTU26I2EU7ltkWPwxvucQTuqMm8dUz72z2YMqTD6s9vMcDUysk7n9jnC+lXuCPeJJ7Knf98VEYE9Rg==} + engines: {node: '>=16'} + peerDependencies: + react: ^16.3.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 + + react-dom@19.1.0: + resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} + peerDependencies: + react: ^19.1.0 + + react-hot-toast@2.6.0: + resolution: {integrity: sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16' + react-dom: '>=16' + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react@19.1.0: + resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} + engines: {node: '>=0.10.0'} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + scheduler@0.26.0: + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + sharp@0.34.4: + resolution: {integrity: sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + socket.io-adapter@2.5.5: + resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} + + socket.io-client@4.8.1: + resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==} + engines: {node: '>=10.0.0'} + + socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + + socket.io@4.8.1: + resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} + engines: {node: '>=10.2.0'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stable-hash@0.0.5: + resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + string.prototype.includes@2.0.1: + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} + + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tailwindcss@4.1.13: + resolution: {integrity: sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==} + + tapable@2.2.3: + resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==} + engines: {node: '>=6'} + + tar@7.5.1: + resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==} + engines: {node: '>=18'} + + tiny-case@1.0.3: + resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.20.6: + resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==} + engines: {node: '>=18.0.0'} + hasBin: true + + tween-functions@1.2.0: + resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typescript@5.9.2: + resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + engines: {node: '>=14.17'} + hasBin: true + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + use-sound@5.0.0: + resolution: {integrity: sha512-MNHT3FFC5HxNCrgZtrnpIMJI2cw/0D2xismcrtyht8BTuF5FhFhb57xO/jlQr2xJaFrc/0btzRQvGyHQwB7PVA==} + peerDependencies: + react: '>=16.8' + + uuid@13.0.0: + resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} + hasBin: true + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + 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 + + xmlhttprequest-ssl@2.1.2: + resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} + engines: {node: '>=0.4.0'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yup@1.7.1: + resolution: {integrity: sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==} + + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zod@4.1.11: + resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} + + zod@4.1.12: + resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==} + + zustand@5.0.8: + resolution: {integrity: sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.4': {} + + '@babel/core@7.28.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.4 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.3': + dependencies: + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.4 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.26.3 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.4': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.4 + + '@babel/parser@7.28.4': + dependencies: + '@babel/types': 7.28.4 + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + + '@babel/traverse@7.28.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.4 + '@babel/template': 7.27.2 + '@babel/types': 7.28.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.4': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@emnapi/core@1.5.0': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.5.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.25.10': + optional: true + + '@esbuild/android-arm64@0.25.10': + optional: true + + '@esbuild/android-arm@0.25.10': + optional: true + + '@esbuild/android-x64@0.25.10': + optional: true + + '@esbuild/darwin-arm64@0.25.10': + optional: true + + '@esbuild/darwin-x64@0.25.10': + optional: true + + '@esbuild/freebsd-arm64@0.25.10': + optional: true + + '@esbuild/freebsd-x64@0.25.10': + optional: true + + '@esbuild/linux-arm64@0.25.10': + optional: true + + '@esbuild/linux-arm@0.25.10': + optional: true + + '@esbuild/linux-ia32@0.25.10': + optional: true + + '@esbuild/linux-loong64@0.25.10': + optional: true + + '@esbuild/linux-mips64el@0.25.10': + optional: true + + '@esbuild/linux-ppc64@0.25.10': + optional: true + + '@esbuild/linux-riscv64@0.25.10': + optional: true + + '@esbuild/linux-s390x@0.25.10': + optional: true + + '@esbuild/linux-x64@0.25.10': + optional: true + + '@esbuild/netbsd-arm64@0.25.10': + optional: true + + '@esbuild/netbsd-x64@0.25.10': + optional: true + + '@esbuild/openbsd-arm64@0.25.10': + optional: true + + '@esbuild/openbsd-x64@0.25.10': + optional: true + + '@esbuild/openharmony-arm64@0.25.10': + optional: true + + '@esbuild/sunos-x64@0.25.10': + optional: true + + '@esbuild/win32-arm64@0.25.10': + optional: true + + '@esbuild/win32-ia32@0.25.10': + optional: true + + '@esbuild/win32-x64@0.25.10': + optional: true + + '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.0))': + dependencies: + eslint: 9.36.0(jiti@2.6.0) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.3.1': {} + + '@eslint/core@0.15.2': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.36.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.5': + dependencies: + '@eslint/core': 0.15.2 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@img/colour@1.0.0': + optional: true + + '@img/sharp-darwin-arm64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.3 + optional: true + + '@img/sharp-darwin-x64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.3 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.3': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.3': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.3': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.3': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.3': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.3': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.3': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.3': + optional: true + + '@img/sharp-linux-arm64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.3 + optional: true + + '@img/sharp-linux-arm@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.3 + optional: true + + '@img/sharp-linux-ppc64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.3 + optional: true + + '@img/sharp-linux-s390x@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.3 + optional: true + + '@img/sharp-linux-x64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.3 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 + optional: true + + '@img/sharp-wasm32@0.34.4': + dependencies: + '@emnapi/runtime': 1.5.0 + optional: true + + '@img/sharp-win32-arm64@0.34.4': + optional: true + + '@img/sharp-win32-ia32@0.34.4': + optional: true + + '@img/sharp-win32-x64@0.34.4': + optional: true + + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@napi-rs/wasm-runtime@0.2.12': + dependencies: + '@emnapi/core': 1.5.0 + '@emnapi/runtime': 1.5.0 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@next/env@15.5.4': {} + + '@next/eslint-plugin-next@15.5.4': + dependencies: + fast-glob: 3.3.1 + + '@next/swc-darwin-arm64@15.5.4': + optional: true + + '@next/swc-darwin-x64@15.5.4': + optional: true + + '@next/swc-linux-arm64-gnu@15.5.4': + optional: true + + '@next/swc-linux-arm64-musl@15.5.4': + optional: true + + '@next/swc-linux-x64-gnu@15.5.4': + optional: true + + '@next/swc-linux-x64-musl@15.5.4': + optional: true + + '@next/swc-win32-arm64-msvc@15.5.4': + optional: true + + '@next/swc-win32-x64-msvc@15.5.4': + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@nolyfill/is-core-module@1.0.39': {} + + '@rtsao/scc@1.1.0': {} + + '@rushstack/eslint-patch@1.12.0': {} + + '@socket.io/component-emitter@3.1.2': {} + + '@swc/helpers@0.5.15': + dependencies: + tslib: 2.8.1 + + '@t3-oss/env-core@0.13.8(typescript@5.9.2)(zod@4.1.11)': + optionalDependencies: + typescript: 5.9.2 + zod: 4.1.11 + + '@t3-oss/env-core@0.13.8(typescript@5.9.2)(zod@4.1.12)': + optionalDependencies: + typescript: 5.9.2 + zod: 4.1.12 + + '@t3-oss/env-nextjs@0.13.8(typescript@5.9.2)(zod@4.1.12)': + dependencies: + '@t3-oss/env-core': 0.13.8(typescript@5.9.2)(zod@4.1.12) + optionalDependencies: + typescript: 5.9.2 + zod: 4.1.12 + + '@tailwindcss/node@4.1.13': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.18.3 + jiti: 2.6.0 + lightningcss: 1.30.1 + magic-string: 0.30.19 + source-map-js: 1.2.1 + tailwindcss: 4.1.13 + + '@tailwindcss/oxide-android-arm64@4.1.13': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.13': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.13': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.13': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.13': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.13': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.13': + optional: true + + '@tailwindcss/oxide@4.1.13': + dependencies: + detect-libc: 2.1.1 + tar: 7.5.1 + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.13 + '@tailwindcss/oxide-darwin-arm64': 4.1.13 + '@tailwindcss/oxide-darwin-x64': 4.1.13 + '@tailwindcss/oxide-freebsd-x64': 4.1.13 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.13 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.13 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.13 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.13 + '@tailwindcss/oxide-linux-x64-musl': 4.1.13 + '@tailwindcss/oxide-wasm32-wasi': 4.1.13 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.13 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.13 + + '@tailwindcss/postcss@4.1.13': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.1.13 + '@tailwindcss/oxide': 4.1.13 + postcss: 8.5.6 + tailwindcss: 4.1.13 + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/cors@2.8.19': + dependencies: + '@types/node': 20.19.17 + + '@types/estree@1.0.8': {} + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/node@20.19.17': + dependencies: + undici-types: 6.21.0 + + '@types/react-dom@19.1.9(@types/react@19.1.15)': + dependencies: + '@types/react': 19.1.15 + + '@types/react@19.1.15': + dependencies: + csstype: 3.1.3 + + '@typescript-eslint/eslint-plugin@8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + '@typescript-eslint/scope-manager': 8.45.0 + '@typescript-eslint/type-utils': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.45.0 + eslint: 9.36.0(jiti@2.6.0) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.45.0 + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.45.0 + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.0) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.45.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.2) + '@typescript-eslint/types': 8.45.0 + debug: 4.4.3 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.45.0': + dependencies: + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/visitor-keys': 8.45.0 + + '@typescript-eslint/tsconfig-utils@8.45.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@typescript-eslint/type-utils@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)': + dependencies: + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.0) + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.45.0': {} + + '@typescript-eslint/typescript-estree@8.45.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/project-service': 8.45.0(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.2) + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/visitor-keys': 8.45.0 + debug: 4.4.3 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0)) + '@typescript-eslint/scope-manager': 8.45.0 + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) + eslint: 9.36.0(jiti@2.6.0) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.45.0': + dependencies: + '@typescript-eslint/types': 8.45.0 + eslint-visitor-keys: 4.2.1 + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + aria-query@5.3.2: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-includes@3.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.findlastindex@1.2.6: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-shim-unscopables: 1.1.0 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + ast-types-flow@0.0.8: {} + + async-function@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axe-core@4.10.3: {} + + axobject-query@4.1.0: {} + + balanced-match@1.0.2: {} + + base64id@2.0.0: {} + + baseline-browser-mapping@2.8.12: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.26.3: + dependencies: + baseline-browser-mapping: 2.8.12 + caniuse-lite: 1.0.30001747 + electron-to-chromium: 1.5.230 + node-releases: 2.0.23 + update-browserslist-db: 1.1.3(browserslist@4.26.3) + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001745: {} + + caniuse-lite@1.0.30001747: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chownr@3.0.0: {} + + client-only@0.0.1: {} + + clsx@2.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + concat-map@0.0.1: {} + + convert-source-map@2.0.0: {} + + cookie@0.7.2: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.1.3: {} + + damerau-levenshtein@1.0.8: {} + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + detect-libc@2.1.1: {} + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dotenv-cli@10.0.0: + dependencies: + cross-spawn: 7.0.6 + dotenv: 17.2.3 + dotenv-expand: 11.0.7 + minimist: 1.2.8 + + dotenv-expand@11.0.7: + dependencies: + dotenv: 16.6.1 + + dotenv@16.6.1: {} + + dotenv@17.2.3: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + electron-to-chromium@1.5.230: {} + + emoji-regex@9.2.2: {} + + engine.io-client@6.6.3: + 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.1.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + engine.io-parser@5.2.3: {} + + engine.io@6.6.4: + dependencies: + '@types/cors': 2.8.19 + '@types/node': 20.19.17 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.7.2 + cors: 2.8.5 + debug: 4.3.7 + engine.io-parser: 5.2.3 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + enhanced-resolve@5.18.3: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.3 + + es-abstract@1.24.0: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-iterator-helpers@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + safe-array-concat: 1.1.3 + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.25.10: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.10 + '@esbuild/android-arm': 0.25.10 + '@esbuild/android-arm64': 0.25.10 + '@esbuild/android-x64': 0.25.10 + '@esbuild/darwin-arm64': 0.25.10 + '@esbuild/darwin-x64': 0.25.10 + '@esbuild/freebsd-arm64': 0.25.10 + '@esbuild/freebsd-x64': 0.25.10 + '@esbuild/linux-arm': 0.25.10 + '@esbuild/linux-arm64': 0.25.10 + '@esbuild/linux-ia32': 0.25.10 + '@esbuild/linux-loong64': 0.25.10 + '@esbuild/linux-mips64el': 0.25.10 + '@esbuild/linux-ppc64': 0.25.10 + '@esbuild/linux-riscv64': 0.25.10 + '@esbuild/linux-s390x': 0.25.10 + '@esbuild/linux-x64': 0.25.10 + '@esbuild/netbsd-arm64': 0.25.10 + '@esbuild/netbsd-x64': 0.25.10 + '@esbuild/openbsd-arm64': 0.25.10 + '@esbuild/openbsd-x64': 0.25.10 + '@esbuild/openharmony-arm64': 0.25.10 + '@esbuild/sunos-x64': 0.25.10 + '@esbuild/win32-arm64': 0.25.10 + '@esbuild/win32-ia32': 0.25.10 + '@esbuild/win32-x64': 0.25.10 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-next@15.5.4(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2): + dependencies: + '@next/eslint-plugin-next': 15.5.4 + '@rushstack/eslint-patch': 1.12.0 + '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + eslint: 9.36.0(jiti@2.6.0) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.0)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.36.0(jiti@2.6.0)) + eslint-plugin-react: 7.37.5(eslint@9.36.0(jiti@2.6.0)) + eslint-plugin-react-hooks: 5.2.0(eslint@9.36.0(jiti@2.6.0)) + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - supports-color + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.0)): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.0) + get-tsconfig: 4.10.1 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.15 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)) + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + eslint: 9.36.0(jiti@2.6.0) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.0)) + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.36.0(jiti@2.6.0) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jsx-a11y@6.10.2(eslint@9.36.0(jiti@2.6.0)): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.9 + array.prototype.flatmap: 1.3.3 + ast-types-flow: 0.0.8 + axe-core: 4.10.3 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 9.36.0(jiti@2.6.0) + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + safe-regex-test: 1.1.0 + string.prototype.includes: 2.0.1 + + eslint-plugin-react-hooks@5.2.0(eslint@9.36.0(jiti@2.6.0)): + dependencies: + eslint: 9.36.0(jiti@2.6.0) + + eslint-plugin-react-hooks@6.1.1(eslint@9.36.0(jiti@2.6.0)): + dependencies: + '@babel/core': 7.28.4 + '@babel/parser': 7.28.4 + eslint: 9.36.0(jiti@2.6.0) + zod: 4.1.12 + zod-validation-error: 4.0.2(zod@4.1.12) + transitivePeerDependencies: + - supports-color + + eslint-plugin-react@7.37.5(eslint@9.36.0(jiti@2.6.0)): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.36.0(jiti@2.6.0) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.36.0(jiti@2.6.0): + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.1 + '@eslint/core': 0.15.2 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.36.0 + '@eslint/plugin-kit': 0.3.5 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.0 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.1: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + gensync@1.0.0-beta.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@14.0.0: {} + + globals@16.4.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + goober@2.1.16(csstype@3.1.3): + dependencies: + csstype: 3.1.3 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + howler@2.2.4: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-bun-module@2.0.0: + dependencies: + semver: 7.7.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.19 + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + + jiti@2.6.0: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.9 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + ky@1.11.0: {} + + language-subtag-registry@0.3.23: {} + + language-tags@1.0.9: + dependencies: + language-subtag-registry: 0.3.23 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-darwin-arm64@1.30.1: + optional: true + + lightningcss-darwin-x64@1.30.1: + optional: true + + lightningcss-freebsd-x64@1.30.1: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.1: + optional: true + + lightningcss-linux-arm64-gnu@1.30.1: + optional: true + + lightningcss-linux-arm64-musl@1.30.1: + optional: true + + lightningcss-linux-x64-gnu@1.30.1: + optional: true + + lightningcss-linux-x64-musl@1.30.1: + optional: true + + lightningcss-win32-arm64-msvc@1.30.1: + optional: true + + lightningcss-win32-x64-msvc@1.30.1: + optional: true + + lightningcss@1.30.1: + dependencies: + detect-libc: 2.1.1 + optionalDependencies: + lightningcss-darwin-arm64: 1.30.1 + lightningcss-darwin-x64: 1.30.1 + lightningcss-freebsd-x64: 1.30.1 + lightningcss-linux-arm-gnueabihf: 1.30.1 + lightningcss-linux-arm64-gnu: 1.30.1 + lightningcss-linux-arm64-musl: 1.30.1 + lightningcss-linux-x64-gnu: 1.30.1 + lightningcss-linux-x64-musl: 1.30.1 + lightningcss-win32-arm64-msvc: 1.30.1 + lightningcss-win32-x64-msvc: 1.30.1 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.19: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + minizlib@3.1.0: + dependencies: + minipass: 7.1.2 + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + napi-postinstall@0.3.3: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + next@15.5.4(@babel/core@7.28.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + '@next/env': 15.5.4 + '@swc/helpers': 0.5.15 + caniuse-lite: 1.0.30001745 + postcss: 8.4.31 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + styled-jsx: 5.1.6(@babel/core@7.28.4)(react@19.1.0) + optionalDependencies: + '@next/swc-darwin-arm64': 15.5.4 + '@next/swc-darwin-x64': 15.5.4 + '@next/swc-linux-arm64-gnu': 15.5.4 + '@next/swc-linux-arm64-musl': 15.5.4 + '@next/swc-linux-x64-gnu': 15.5.4 + '@next/swc-linux-x64-musl': 15.5.4 + '@next/swc-win32-arm64-msvc': 15.5.4 + '@next/swc-win32-x64-msvc': 15.5.4 + sharp: 0.34.4 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + node-releases@2.0.23: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + possible-typed-array-names@1.1.0: {} + + postcss@8.4.31: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier-plugin-tailwindcss@0.6.14(prettier@3.6.2): + dependencies: + prettier: 3.6.2 + + prettier@3.6.2: {} + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + property-expr@2.0.6: {} + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + react-confetti@6.4.0(react@19.1.0): + dependencies: + react: 19.1.0 + tween-functions: 1.2.0 + + react-dom@19.1.0(react@19.1.0): + dependencies: + react: 19.1.0 + scheduler: 0.26.0 + + react-hot-toast@2.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + csstype: 3.1.3 + goober: 2.1.16(csstype@3.1.3) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + + react-is@16.13.1: {} + + react@19.1.0: {} + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + resolve-from@4.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + scheduler@0.26.0: {} + + semver@6.3.1: {} + + semver@7.7.2: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + sharp@0.34.4: + dependencies: + '@img/colour': 1.0.0 + detect-libc: 2.1.1 + semver: 7.7.2 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.4 + '@img/sharp-darwin-x64': 0.34.4 + '@img/sharp-libvips-darwin-arm64': 1.2.3 + '@img/sharp-libvips-darwin-x64': 1.2.3 + '@img/sharp-libvips-linux-arm': 1.2.3 + '@img/sharp-libvips-linux-arm64': 1.2.3 + '@img/sharp-libvips-linux-ppc64': 1.2.3 + '@img/sharp-libvips-linux-s390x': 1.2.3 + '@img/sharp-libvips-linux-x64': 1.2.3 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 + '@img/sharp-linux-arm': 0.34.4 + '@img/sharp-linux-arm64': 0.34.4 + '@img/sharp-linux-ppc64': 0.34.4 + '@img/sharp-linux-s390x': 0.34.4 + '@img/sharp-linux-x64': 0.34.4 + '@img/sharp-linuxmusl-arm64': 0.34.4 + '@img/sharp-linuxmusl-x64': 0.34.4 + '@img/sharp-wasm32': 0.34.4 + '@img/sharp-win32-arm64': 0.34.4 + '@img/sharp-win32-ia32': 0.34.4 + '@img/sharp-win32-x64': 0.34.4 + optional: true + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + socket.io-adapter@2.5.5: + dependencies: + debug: 4.3.7 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-client@4.8.1: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + engine.io-client: 6.6.3 + 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 + + socket.io@4.8.1: + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cors: 2.8.5 + debug: 4.3.7 + engine.io: 6.6.4 + socket.io-adapter: 2.5.5 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + source-map-js@1.2.1: {} + + stable-hash@0.0.5: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + string.prototype.includes@2.0.1: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.0 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.24.0 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + strip-bom@3.0.0: {} + + strip-json-comments@3.1.1: {} + + styled-jsx@5.1.6(@babel/core@7.28.4)(react@19.1.0): + dependencies: + client-only: 0.0.1 + react: 19.1.0 + optionalDependencies: + '@babel/core': 7.28.4 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + tailwindcss@4.1.13: {} + + tapable@2.2.3: {} + + tar@7.5.1: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.1.0 + yallist: 5.0.0 + + tiny-case@1.0.3: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toposort@2.0.2: {} + + ts-api-utils@2.1.0(typescript@5.9.2): + dependencies: + typescript: 5.9.2 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.8.1: {} + + tsx@4.20.6: + dependencies: + esbuild: 0.25.10 + get-tsconfig: 4.10.1 + optionalDependencies: + fsevents: 2.3.3 + + tween-functions@1.2.0: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@2.19.0: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typescript@5.9.2: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + undici-types@6.21.0: {} + + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.3 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + + update-browserslist-db@1.1.3(browserslist@4.26.3): + dependencies: + browserslist: 4.26.3 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + use-sound@5.0.0(react@19.1.0): + dependencies: + howler: 2.2.4 + react: 19.1.0 + + uuid@13.0.0: {} + + vary@1.1.2: {} + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.0 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + ws@8.17.1: {} + + xmlhttprequest-ssl@2.1.2: {} + + yallist@3.1.1: {} + + yallist@5.0.0: {} + + yocto-queue@0.1.0: {} + + yup@1.7.1: + dependencies: + property-expr: 2.0.6 + tiny-case: 1.0.3 + toposort: 2.0.2 + type-fest: 2.19.0 + + zod-validation-error@4.0.2(zod@4.1.12): + dependencies: + zod: 4.1.12 + + zod@3.25.76: {} + + zod@4.1.11: {} + + zod@4.1.12: {} + + zustand@5.0.8(@types/react@19.1.15)(react@19.1.0): + optionalDependencies: + '@types/react': 19.1.15 + react: 19.1.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..dee51e9 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - "packages/*" diff --git a/postcss.config.js b/postcss.config.js deleted file mode 100644 index 33ad091..0000000 --- a/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/socket/index.js b/socket/index.js deleted file mode 100644 index dd0dd0f..0000000 --- a/socket/index.js +++ /dev/null @@ -1,74 +0,0 @@ -import { Server } from "socket.io" -import { GAME_STATE_INIT, WEBSOCKET_SERVER_PORT } from "../config.mjs" -import Manager from "./roles/manager.js" -import Player from "./roles/player.js" -import { abortCooldown } from "./utils/cooldown.js" -import deepClone from "./utils/deepClone.js" - -let gameState = deepClone(GAME_STATE_INIT) - -const io = new Server({ - cors: { - origin: "*", - }, -}) - -console.log(`Server running on port ${WEBSOCKET_SERVER_PORT}`) -io.listen(WEBSOCKET_SERVER_PORT) - -io.on("connection", (socket) => { - console.log(`A user connected ${socket.id}`) - - socket.on("player:checkRoom", (roomId) => - Player.checkRoom(gameState, io, socket, roomId), - ) - - socket.on("player:join", (player) => - Player.join(gameState, io, socket, player), - ) - - socket.on("manager:createRoom", (password) => - Manager.createRoom(gameState, io, socket, password), - ) - socket.on("manager:kickPlayer", (playerId) => - Manager.kickPlayer(gameState, io, socket, playerId), - ) - - socket.on("manager:startGame", () => Manager.startGame(gameState, io, socket)) - - socket.on("player:selectedAnswer", (answerKey) => - Player.selectedAnswer(gameState, io, socket, answerKey), - ) - - socket.on("manager:abortQuiz", () => Manager.abortQuiz(gameState, io, socket)) - - socket.on("manager:nextQuestion", () => - Manager.nextQuestion(gameState, io, socket), - ) - - socket.on("manager:showLeaderboard", () => - Manager.showLoaderboard(gameState, io, socket), - ) - - socket.on("disconnect", () => { - console.log(`user disconnected ${socket.id}`) - - if (gameState.manager === socket.id) { - console.log("Reset game") - io.to(gameState.room).emit("game:reset") - gameState.started = false - gameState = deepClone(GAME_STATE_INIT) - - abortCooldown() - - return - } - - const player = gameState.players.find((p) => p.id === socket.id) - - if (player) { - gameState.players = gameState.players.filter((p) => p.id !== socket.id) - socket.to(gameState.manager).emit("manager:removePlayer", player.id) - } - }) -}) diff --git a/socket/package.json b/socket/package.json deleted file mode 100644 index 3dbc1ca..0000000 --- a/socket/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/socket/roles/manager.js b/socket/roles/manager.js deleted file mode 100644 index b993e10..0000000 --- a/socket/roles/manager.js +++ /dev/null @@ -1,123 +0,0 @@ -import { GAME_STATE_INIT } from "../../config.mjs" -import { abortCooldown, cooldown, sleep } from "../utils/cooldown.js" -import deepClone from "../utils/deepClone.js" -import generateRoomId from "../utils/generateRoomId.js" -import { startRound } from "../utils/round.js" - -const Manager = { - createRoom: (game, io, socket, password) => { - if (game.password !== password) { - io.to(socket.id).emit("game:errorMessage", "Bad Password") - - return - } - - if (game.manager || game.room) { - io.to(socket.id).emit("game:errorMessage", "Already manager") - - return - } - - const roomInvite = generateRoomId() - game.room = roomInvite - game.manager = socket.id - - socket.join(roomInvite) - io.to(socket.id).emit("manager:inviteCode", roomInvite) - - console.log(`New room created: ${roomInvite}`) - }, - - kickPlayer: (game, io, socket, playerId) => { - if (game.manager !== socket.id) { - return - } - - const player = game.players.find((p) => p.id === playerId) - game.players = game.players.filter((p) => p.id !== playerId) - - io.in(playerId).socketsLeave(game.room) - io.to(player.id).emit("game:kick") - io.to(game.manager).emit("manager:playerKicked", player.id) - - io.to(game.room).emit("game:totalPlayers", game.players.length) - }, - - startGame: async (game, io, socket) => { - if (game.started || !game.room) { - return - } - - game.started = true - io.to(game.room).emit("game:status", { - name: "SHOW_START", - data: { - time: 3, - subject: game.subject, - }, - }) - - await sleep(3) - io.to(game.room).emit("game:startCooldown") - - await cooldown(3, io, game.room) - startRound(game, io, socket) - }, - - nextQuestion: (game, io, socket) => { - if (!game.started) { - return - } - - if (socket.id !== game.manager) { - return - } - - if (!game.questions[game.currentQuestion + 1]) { - return - } - - game.currentQuestion += 1 - startRound(game, io, socket) - }, - - abortQuiz: (game, io, socket) => { - if (!game.started) { - return - } - - if (socket.id !== game.manager) { - return - } - - abortCooldown(game, io, game.room) - }, - - showLoaderboard: (game, io, socket) => { - if (!game.questions[game.currentQuestion + 1]) { - socket.emit("game:status", { - name: "FINISH", - data: { - subject: game.subject, - top: game.players.slice(0, 3).sort((a, b) => b.points - a.points), - }, - }) - - // eslint-disable-next-line no-param-reassign - game = deepClone(GAME_STATE_INIT) - - return - } - - socket.emit("game:status", { - name: "SHOW_LEADERBOARD", - data: { - leaderboard: game.players - .sort((a, b) => b.points - a.points) - .slice(0, 5), - }, - }) - }, -} - -export default Manager diff --git a/socket/roles/player.js b/socket/roles/player.js deleted file mode 100644 index 5359e58..0000000 --- a/socket/roles/player.js +++ /dev/null @@ -1,104 +0,0 @@ -import convertTimeToPoint from "../utils/convertTimeToPoint.js" -import { abortCooldown } from "../utils/cooldown.js" -import { inviteCodeValidator, usernameValidator } from "../validator.js" - -const Player = { - checkRoom: async (game, io, socket, roomId) => { - try { - await inviteCodeValidator.validate(roomId) - } catch (error) { - socket.emit("game:errorMessage", error.errors[0]) - - return - } - - if (!game.room || roomId !== game.room) { - socket.emit("game:errorMessage", "Room not found") - - return - } - - socket.emit("game:successRoom", roomId) - }, - - join: async (game, io, socket, player) => { - try { - await usernameValidator.validate(player.username) - } catch (error) { - socket.emit("game:errorMessage", error.errors[0]) - - return - } - - if (!game.room || player.room !== game.room) { - socket.emit("game:errorMessage", "Room not found") - - return - } - - if (game.players.find((p) => p.username === player.username)) { - socket.emit("game:errorMessage", "Username already exists") - - return - } - - if (game.started) { - socket.emit("game:errorMessage", "Game already started") - - return - } - - console.log("New Player", player) - - socket.join(player.room) - - const playerData = { - username: player.username, - room: player.room, - id: socket.id, - points: 0, - } - socket.to(player.room).emit("manager:newPlayer", { ...playerData }) - - game.players.push(playerData) - - // Emit total players to all players in the room - io.to(player.room).emit("game:totalPlayers", game.players.length) - - socket.emit("game:successJoin") - }, - - selectedAnswer: (game, io, socket, answerKey) => { - const player = game.players.find((player) => player.id === socket.id) - - const question = game.questions[game.currentQuestion] - - if (!player) { - return - } - - if (game.playersAnswer.find((p) => p.id === socket.id)) { - return - } - - game.playersAnswer.push({ - id: socket.id, - answer: answerKey, - points: convertTimeToPoint(game.roundStartTime, question.time), - }) - - socket.emit("game:status", { - name: "WAIT", - data: { text: "Waiting for the players to answer" }, - }) - socket.to(game.room).emit("game:playerAnswer", game.playersAnswer.length) - - io.to(game.room).emit("game:totalPlayers", game.players.length) - - if (game.playersAnswer.length === game.players.length) { - abortCooldown() - } - }, -} - -export default Player diff --git a/socket/utils/convertTimeToPoint.js b/socket/utils/convertTimeToPoint.js deleted file mode 100644 index 88ff8c3..0000000 --- a/socket/utils/convertTimeToPoint.js +++ /dev/null @@ -1,13 +0,0 @@ -const convertTimeToPoint = (startTime, secondes) => { - let points = 1000 - - const actualTime = Date.now() - const tempsPasseEnSecondes = (actualTime - startTime) / 1000 - - points -= (1000 / secondes) * tempsPasseEnSecondes - points = Math.max(0, points) - - return points -} - -export default convertTimeToPoint diff --git a/socket/utils/cooldown.js b/socket/utils/cooldown.js deleted file mode 100644 index f6b4fba..0000000 --- a/socket/utils/cooldown.js +++ /dev/null @@ -1,30 +0,0 @@ -let cooldownTimeout = null -let cooldownResolve = null - -export const abortCooldown = () => { - clearInterval(cooldownTimeout) - - if (cooldownResolve) { - cooldownResolve() - } -} - -export const cooldown = (ms, io, room) => { - let count = ms - 1 - - return new Promise((resolve) => { - cooldownResolve = resolve - - cooldownTimeout = setInterval(() => { - if (!count) { - clearInterval(cooldownTimeout) - resolve() - } - - io.to(room).emit("game:cooldown", count) - count -= 1 - }, 1000) - }) -} - -export const sleep = (sec) => new Promise((r) => void setTimeout(r, sec * 1000)) diff --git a/socket/utils/deepClone.js b/socket/utils/deepClone.js deleted file mode 100644 index f7522d0..0000000 --- a/socket/utils/deepClone.js +++ /dev/null @@ -1,20 +0,0 @@ -const deepClone = (obj) => { - if (obj === null || typeof obj !== "object") { - return obj - } - - if (Array.isArray(obj)) { - return obj.map(deepClone) - } - - const clonedObj = {} - for (const key in obj) { - if (Object.hasOwn(obj, key)) { - clonedObj[key] = deepClone(obj[key]) - } - } - - return clonedObj -} - -export default deepClone diff --git a/socket/utils/round.js b/socket/utils/round.js deleted file mode 100644 index 48f2ea5..0000000 --- a/socket/utils/round.js +++ /dev/null @@ -1,114 +0,0 @@ -import { cooldown, sleep } from "./cooldown.js" - -export const startRound = async (game, io) => { - const question = game.questions[game.currentQuestion] - - if (!game.started) { - return - } - - io.to(game.room).emit("game:updateQuestion", { - current: game.currentQuestion + 1, - total: game.questions.length, - }) - - io.to(game.room).emit("game:status", { - name: "SHOW_PREPARED", - data: { - totalAnswers: game.questions[game.currentQuestion].answers.length, - questionNumber: game.currentQuestion + 1, - }, - }) - - await sleep(2) - - if (!game.started) { - return - } - - io.to(game.room).emit("game:status", { - name: "SHOW_QUESTION", - data: { - question: question.question, - image: question.image, - cooldown: question.cooldown, - }, - }) - - await sleep(question.cooldown) - - if (!game.started) { - return - } - - game.roundStartTime = Date.now() - - io.to(game.room).emit("game:status", { - name: "SELECT_ANSWER", - data: { - question: question.question, - answers: question.answers, - image: question.image, - time: question.time, - totalPlayer: game.players.length, - }, - }) - - await cooldown(question.time, io, game.room) - - if (!game.started) { - return - } - - game.players.map(async (player) => { - const playerAnswer = await game.playersAnswer.find( - (p) => p.id === player.id, - ) - - const isCorrect = playerAnswer - ? playerAnswer.answer === question.solution - : false - - const points = - (isCorrect && Math.round(playerAnswer && playerAnswer.points)) || 0 - - player.points += points - - const sortPlayers = game.players.sort((a, b) => b.points - a.points) - - const rank = sortPlayers.findIndex((p) => p.id === player.id) + 1 - const aheadPlayer = sortPlayers[rank - 2] - - io.to(player.id).emit("game:status", { - name: "SHOW_RESULT", - data: { - correct: isCorrect, - message: isCorrect ? "Nice !" : "Too bad", - points, - myPoints: player.points, - rank, - aheadOfMe: aheadPlayer ? aheadPlayer.username : null, - }, - }) - }) - - const totalType = {} - - game.playersAnswer.forEach(({ answer }) => { - totalType[answer] = (totalType[answer] || 0) + 1 - }) - - // Manager - io.to(game.manager).emit("game:status", { - name: "SHOW_RESPONSES", - data: { - question: game.questions[game.currentQuestion].question, - responses: totalType, - correct: game.questions[game.currentQuestion].solution, - answers: game.questions[game.currentQuestion].answers, - image: game.questions[game.currentQuestion].image, - }, - }) - - game.playersAnswer = [] -} diff --git a/socket/validator.js b/socket/validator.js deleted file mode 100644 index 2c6f0dc..0000000 --- a/socket/validator.js +++ /dev/null @@ -1,12 +0,0 @@ -import yup from "yup" - -export const usernameValidator = yup - .string() - .required("Username is required") - .min(4, "Username cannot be less than 4 characters") - .max(20, "Username cannot exceed 20 characters") - -export const inviteCodeValidator = yup - .string() - .required("Invite code is required") - .length(6, "Invalid invite code") diff --git a/src/components/Input.jsx b/src/components/Input.jsx deleted file mode 100644 index 663b49b..0000000 --- a/src/components/Input.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import clsx from "clsx" - -export default function Input({ className, ...otherProps }) { - return ( - - ) -} diff --git a/src/components/ManagerPassword.jsx b/src/components/ManagerPassword.jsx deleted file mode 100644 index d1b9234..0000000 --- a/src/components/ManagerPassword.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import logo from "@/assets/logo.svg" -import Button from "@/components/Button" -import Form from "@/components/Form" -import Input from "@/components/Input" -import { socket } from "@/context/socket" -import Image from "next/image" -import { useEffect, useState } from "react" -import toast from "react-hot-toast" - -export default function ManagerPassword() { - const [password, setPassword] = useState("") - - const handleCreate = () => { - socket.emit("manager:createRoom", password) - } - - const handleKeyDown = (event) => { - if (event.key === "Enter") { - handleCreate() - } - } - - useEffect(() => { - socket.on("game:errorMessage", (message) => { - toast.error(message) - }) - - return () => { - socket.off("game:errorMessage") - } - }, []) - - return ( -
-
-
-
-
- - logo - -
- setPassword(e.target.value)} - onKeyDown={handleKeyDown} - placeholder="Manager password" - /> - -
-
- ) -} diff --git a/src/components/game/GameWrapper.jsx b/src/components/game/GameWrapper.jsx deleted file mode 100644 index 8e284d4..0000000 --- a/src/components/game/GameWrapper.jsx +++ /dev/null @@ -1,77 +0,0 @@ -import background from "@/assets/background.webp" -import Button from "@/components/Button" -import { usePlayerContext } from "@/context/player" -import { useSocketContext } from "@/context/socket" -import Image from "next/image" -import { useRouter } from "next/router" -import { useEffect, useState } from "react" - -export default function GameWrapper({ children, textNext, onNext, manager }) { - const { socket } = useSocketContext() - const { player, dispatch } = usePlayerContext() - const router = useRouter() - - const [questionState, setQuestionState] = useState() - - useEffect(() => { - socket.on("game:kick", () => { - dispatch({ - type: "LOGOUT", - }) - - router.replace("/") - }) - - socket.on("game:updateQuestion", ({ current, total }) => { - setQuestionState({ - current, - total, - }) - }) - - return () => { - socket.off("game:kick") - socket.off("game:updateQuestion") - } - }, []) - - return ( -
-
- background -
- -
- {questionState && ( -
- {`${questionState.current} / ${questionState.total}`} -
- )} - - {manager && ( - - )} -
- - {children} - - {!manager && ( -
-

{Boolean(player) && player.username}

-
- {Boolean(player) && player.points} -
-
- )} -
- ) -} diff --git a/src/components/game/join/Room.jsx b/src/components/game/join/Room.jsx deleted file mode 100644 index e31cb72..0000000 --- a/src/components/game/join/Room.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import Button from "@/components/Button" -import Form from "@/components/Form" -import Input from "@/components/Input" -import { usePlayerContext } from "@/context/player" -import { socket } from "@/context/socket" -import { useEffect, useState } from "react" - -export default function Room() { - const { dispatch } = usePlayerContext() - const [roomId, setRoomId] = useState("") - - const handleLogin = () => { - socket.emit("player:checkRoom", roomId) - } - - const handleKeyDown = (event) => { - if (event.key === "Enter") { - handleLogin() - } - } - - useEffect(() => { - socket.on("game:successRoom", (roomId) => { - dispatch({ type: "JOIN", payload: roomId }) - }) - - return () => { - socket.off("game:successRoom") - } - }, []) - - return ( -
- setRoomId(e.target.value)} - onKeyDown={handleKeyDown} - placeholder="PIN Code here" - /> - -
- ) -} diff --git a/src/components/game/join/Username.jsx b/src/components/game/join/Username.jsx deleted file mode 100644 index 2f2b3fa..0000000 --- a/src/components/game/join/Username.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import Button from "@/components/Button" -import Form from "@/components/Form" -import Input from "@/components/Input" -import { usePlayerContext } from "@/context/player" -import { useSocketContext } from "@/context/socket" -import { useRouter } from "next/router" -import { useEffect, useState } from "react" - -export default function Username() { - const { socket } = useSocketContext() - const { player, dispatch } = usePlayerContext() - const router = useRouter() - const [username, setUsername] = useState("") - - const handleJoin = () => { - socket.emit("player:join", { username, room: player.room }) - } - - const handleKeyDown = (event) => { - if (event.key === "Enter") { - handleJoin() - } - } - - useEffect(() => { - socket.on("game:successJoin", () => { - dispatch({ - type: "LOGIN", - payload: username, - }) - - router.replace("/game") - }) - - return () => { - socket.off("game:successJoin") - } - }, [username]) - - return ( -
- setUsername(e.target.value)} - onKeyDown={handleKeyDown} - placeholder="Username here" - /> - -
- ) -} diff --git a/src/components/game/states/Answers.jsx b/src/components/game/states/Answers.jsx deleted file mode 100644 index 57f90ea..0000000 --- a/src/components/game/states/Answers.jsx +++ /dev/null @@ -1,189 +0,0 @@ -import { - ANSWERS_COLORS, - ANSWERS_ICONS, - SFX_ANSWERS_MUSIC, - SFX_ANSWERS_SOUND, - SFX_RESULTS_SOUND, -} from "@/constants" -import { usePlayerContext } from "@/context/player" -import { useSocketContext } from "@/context/socket" -import clsx from "clsx" -import { useEffect, useState } from "react" -import useSound from "use-sound" -import AnswerButton from "../../AnswerButton" - -const calculatePercentages = (objectResponses) => { - const keys = Object.keys(objectResponses) - const values = Object.values(objectResponses) - - if (!values.length) { - return [] - } - - const totalSum = values.reduce( - (accumulator, currentValue) => accumulator + currentValue, - 0, - ) - - const result = {} - - keys.forEach((key) => { - result[key] = `${((objectResponses[key] / totalSum) * 100).toFixed()}%` - }) - - return result -} - -export default function Answers({ - data: { question, answers, image, time, responses, correct }, -}) { - const { socket } = useSocketContext() - const { player } = usePlayerContext() - - const [percentages, setPercentages] = useState([]) - const [cooldown, setCooldown] = useState(time) - const [totalAnswer, setTotalAnswer] = useState(0) - const [totalPlayer, setTotalPlayer] = useState(0) - - const [sfxPop] = useSound(SFX_ANSWERS_SOUND, { - volume: 0.1, - }) - - const [sfxResults] = useSound(SFX_RESULTS_SOUND, { - volume: 0.2, - }) - - const [playMusic, { stop: stopMusic, isPlaying }] = useSound( - SFX_ANSWERS_MUSIC, - { - volume: 0.2, - }, - ) - - const handleAnswer = (answer) => { - if (!player) { - return - } - - socket.emit("player:selectedAnswer", answer) - sfxPop() - } - - useEffect(() => { - if (!responses) { - playMusic() - - return - } - - stopMusic() - sfxResults() - - setPercentages(calculatePercentages(responses)) - }, [responses, playMusic, stopMusic]) - - useEffect(() => { - if (!isPlaying) { - playMusic() - } - }, [isPlaying]) - - useEffect( - () => () => { - stopMusic() - }, - [playMusic, stopMusic], - ) - - useEffect(() => { - socket.on("game:cooldown", (sec) => { - setCooldown(sec) - }) - - socket.on("game:playerAnswer", (count) => { - setTotalAnswer(count) - sfxPop() - }) - - socket.on("game:totalPlayers", (total) => { - setTotalPlayer(total) - }) - - return () => { - socket.off("game:cooldown") - socket.off("game:playerAnswer") - socket.off("game:totalPlayers") - } - }, [sfxPop]) - - return ( -
-
-

- {question} -

- - {Boolean(image) && !responses && ( - {question} - )} - - {responses && ( -
- {answers.map((_, key) => ( -
- - {responses[key] || 0} - -
- ))} -
- )} -
- -
- {!responses && ( -
-
- Time - {cooldown} -
-
- Answers - - {totalAnswer}/{totalPlayer} - -
-
- )} - -
- {answers.map((answer, key) => ( - handleAnswer(key)} - > - {answer} - - ))} -
-
-
- ) -} diff --git a/src/components/game/states/Room.jsx b/src/components/game/states/Room.jsx deleted file mode 100644 index 4f95ddd..0000000 --- a/src/components/game/states/Room.jsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useSocketContext } from "@/context/socket" -import { useEffect, useState } from "react" - -export default function Room({ data: { text, inviteCode } }) { - const { socket } = useSocketContext() - const [playerList, setPlayerList] = useState([]) - const [totalPlayers, setTotalPlayers] = useState(0) - - useEffect(() => { - socket.on("manager:newPlayer", (player) => { - setPlayerList([...playerList, player]) - }) - - socket.on("manager:removePlayer", (playerId) => { - setPlayerList(playerList.filter((p) => p.id !== playerId)) - }) - - socket.on("manager:playerKicked", (playerId) => { - setPlayerList(playerList.filter((p) => p.id !== playerId)) - }) - - socket.on("game:totalPlayers", (total) => { - setTotalPlayers(total) - }) - - return () => { - socket.off("manager:newPlayer") - socket.off("manager:removePlayer") - socket.off("manager:playerKicked") - socket.off("game:totalPlayers") - } - }, [playerList]) - - return ( -
-
- {inviteCode} -
- -

- {text} -

- -
- - Players Joined: {totalPlayers} - -
- -
- {playerList.map((player) => ( -
socket.emit("manager:kickPlayer", player.id)} - > - - {player.username} - -
- ))} -
-
- ) -} diff --git a/src/constants.js b/src/constants.js deleted file mode 100644 index 33c2e72..0000000 --- a/src/constants.js +++ /dev/null @@ -1,61 +0,0 @@ -import Answers from "@/components/game/states/Answers" -import Leaderboard from "@/components/game/states/Leaderboard" -import Prepared from "@/components/game/states/Prepared" -import Question from "@/components/game/states/Question" -import Result from "@/components/game/states/Result" -import Start from "@/components/game/states/Start" -import Wait from "@/components/game/states/Wait" -import Podium from "./components/game/states/Podium" -import Room from "./components/game/states/Room" - -import Circle from "@/components/icons/Circle" -import Rhombus from "@/components/icons/Rhombus" -import Square from "@/components/icons/Square" -import Triangle from "@/components/icons/Triangle" - -export const ANSWERS_COLORS = [ - "bg-red-500", - "bg-blue-500", - "bg-yellow-500", - "bg-green-500", -] - -export const ANSWERS_ICONS = [Triangle, Rhombus, Circle, Square] - -export const GAME_STATES = { - status: { - name: "WAIT", - data: { text: "Waiting for the players" }, - }, - question: { - current: 1, - total: null, - }, -} - -export const GAME_STATE_COMPONENTS = { - SELECT_ANSWER: Answers, - SHOW_QUESTION: Question, - WAIT: Wait, - SHOW_START: Start, - SHOW_RESULT: Result, - SHOW_PREPARED: Prepared, -} - -export const GAME_STATE_COMPONENTS_MANAGER = { - ...GAME_STATE_COMPONENTS, - SHOW_ROOM: Room, - SHOW_RESPONSES: Answers, - SHOW_LEADERBOARD: Leaderboard, - FINISH: Podium, -} - -export const SFX_ANSWERS_MUSIC = "/sounds/answersMusic.mp3" -export const SFX_ANSWERS_SOUND = "/sounds/answersSound.mp3" -export const SFX_RESULTS_SOUND = "/sounds/results.mp3" -export const SFX_SHOW_SOUND = "/sounds/show.mp3" -export const SFX_BOUMP_SOUND = "/sounds/boump.mp3" -export const SFX_PODIUM_THREE = "/sounds/three.mp3" -export const SFX_PODIUM_SECOND = "/sounds/second.mp3" -export const SFX_PODIUM_FIRST = "/sounds/first.mp3" -export const SFX_SNEAR_ROOL = "/sounds/snearRoll.mp3" diff --git a/src/context/player.jsx b/src/context/player.jsx deleted file mode 100644 index 595321b..0000000 --- a/src/context/player.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import { createContext, useContext, useReducer } from "react" - -export const PlayerContext = createContext() - -export function playerReducer(state, action) { - switch (action.type) { - case "JOIN": - return { player: { ...state.player, room: action.payload } } - - case "LOGIN": - return { - player: { - ...state.player, - username: action.payload, - points: 0, - }, - } - - case "UPDATE": - return { player: { ...state.player, ...action.payload } } - - case "LOGOUT": - return { player: null } - - default: - return state - } -} - -export const PlayerContextProvider = ({ children }) => { - const [state, dispatch] = useReducer(playerReducer, { - player: null, - }) - - return ( - - {children} - - ) -} - -export function usePlayerContext() { - const context = useContext(PlayerContext) - - if (!context) { - throw Error("usePlayerContext must be used inside an PlayerContextProvider") - } - - return context -} diff --git a/src/context/socket.jsx b/src/context/socket.jsx deleted file mode 100644 index 9832e51..0000000 --- a/src/context/socket.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import { createContext, useContext } from "react" -import { io } from "socket.io-client" -import { WEBSOCKET_PUBLIC_URL } from "../../config.mjs" - -export const socket = io(WEBSOCKET_PUBLIC_URL, { - transports: ["websocket"], -}) - -export const SocketContext = createContext() - -export const SocketContextProvider = ({ children }) => ( - {children} -) - -export function useSocketContext() { - const context = useContext(SocketContext) - - return { socket: context } -} diff --git a/src/pages/_app.js b/src/pages/_app.js deleted file mode 100644 index 3afa4ba..0000000 --- a/src/pages/_app.js +++ /dev/null @@ -1,33 +0,0 @@ -import Toaster from "@/components/Toaster" -import { PlayerContextProvider } from "@/context/player" -import { SocketContextProvider } from "@/context/socket" -import "@/styles/globals.css" -import clsx from "clsx" -import { Montserrat } from "next/font/google" -import Head from "next/head" - -const montserrat = Montserrat({ subsets: ["latin"] }) - -export default function App({ Component, pageProps }) { - return ( - <> - - - Rahoot ! - - - -
- -
-
-
- - - ) -} diff --git a/src/pages/_document.js b/src/pages/_document.js deleted file mode 100644 index 6670ab4..0000000 --- a/src/pages/_document.js +++ /dev/null @@ -1,13 +0,0 @@ -import { Html, Head, Main, NextScript } from "next/document" - -export default function Document() { - return ( - - - -
- - - - ) -} diff --git a/src/pages/game.jsx b/src/pages/game.jsx deleted file mode 100644 index ff3fdbf..0000000 --- a/src/pages/game.jsx +++ /dev/null @@ -1,58 +0,0 @@ -import GameWrapper from "@/components/game/GameWrapper" -import { GAME_STATES, GAME_STATE_COMPONENTS } from "@/constants" -import { usePlayerContext } from "@/context/player" -import { useSocketContext } from "@/context/socket" -import { useRouter } from "next/router" -import { createElement, useEffect, useState } from "react" -import toast from "react-hot-toast" - -export default function Game() { - const router = useRouter() - - const { socket } = useSocketContext() - const { player, dispatch } = usePlayerContext() - - useEffect(() => { - if (!player) { - router.replace("/") - } - }, []) - - const [state, setState] = useState(GAME_STATES) - - useEffect(() => { - socket.on("game:status", (status) => { - setState({ - ...state, - status, - question: { - ...state.question, - current: status.question, - }, - }) - }) - - socket.on("game:reset", () => { - router.replace("/") - - dispatch({ type: "LOGOUT" }) - setState(GAME_STATES) - - toast("The game has been reset by the host") - }) - - return () => { - socket.off("game:status") - socket.off("game:reset") - } - }, [state]) - - return ( - - {GAME_STATE_COMPONENTS[state.status.name] && - createElement(GAME_STATE_COMPONENTS[state.status.name], { - data: state.status.data, - })} - - ) -} diff --git a/src/pages/index.js b/src/pages/index.js deleted file mode 100644 index b875cc5..0000000 --- a/src/pages/index.js +++ /dev/null @@ -1,36 +0,0 @@ -import logo from "@/assets/logo.svg" -import Room from "@/components/game/join/Room" -import Username from "@/components/game/join/Username" -import { usePlayerContext } from "@/context/player" -import { useSocketContext } from "@/context/socket" -import Image from "next/image" -import { useEffect } from "react" -import toast from "react-hot-toast" - -export default function Home() { - const { player } = usePlayerContext() - const { socket } = useSocketContext() - - useEffect(() => { - socket.on("game:errorMessage", (message) => { - toast.error(message) - }) - - return () => { - socket.off("game:errorMessage") - } - }, [socket]) - - return ( -
-
-
-
-
- - logo - - {!player ? : } -
- ) -} diff --git a/src/pages/manager.jsx b/src/pages/manager.jsx deleted file mode 100644 index 7ddd5d3..0000000 --- a/src/pages/manager.jsx +++ /dev/null @@ -1,95 +0,0 @@ -import GameWrapper from "@/components/game/GameWrapper" -import ManagerPassword from "@/components/ManagerPassword" -import { GAME_STATES, GAME_STATE_COMPONENTS_MANAGER } from "@/constants" -import { useSocketContext } from "@/context/socket" -import { createElement, useEffect, useState } from "react" - -export default function Manager() { - const { socket } = useSocketContext() - - const [nextText, setNextText] = useState("Start") - const [state, setState] = useState({ - ...GAME_STATES, - status: { - ...GAME_STATES.status, - name: "SHOW_ROOM", - }, - }) - - useEffect(() => { - socket.on("game:status", (status) => { - setState({ - ...state, - status, - question: { - ...state.question, - current: status.question, - }, - }) - }) - - socket.on("manager:inviteCode", (inviteCode) => { - setState({ - ...state, - created: true, - status: { - ...state.status, - data: { - ...state.status.data, - inviteCode, - }, - }, - }) - }) - - return () => { - socket.off("game:status") - socket.off("manager:inviteCode") - } - }, [state]) - - const handleSkip = () => { - setNextText("Skip") - - switch (state.status.name) { - case "SHOW_ROOM": - socket.emit("manager:startGame") - - break - - case "SELECT_ANSWER": - socket.emit("manager:abortQuiz") - - break - - case "SHOW_RESPONSES": - socket.emit("manager:showLeaderboard") - - break - - case "SHOW_LEADERBOARD": - socket.emit("manager:nextQuestion") - - break - } - } - - return ( - <> - {!state.created ? ( -
- -
- ) : ( - <> - - {GAME_STATE_COMPONENTS_MANAGER[state.status.name] && - createElement(GAME_STATE_COMPONENTS_MANAGER[state.status.name], { - data: state.status.data, - })} - - - )} - - ) -} diff --git a/tailwind.config.js b/tailwind.config.js deleted file mode 100644 index 809cc29..0000000 --- a/tailwind.config.js +++ /dev/null @@ -1,25 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", - "./src/components/**/*.{js,ts,jsx,tsx,mdx}", - "./src/app/**/*.{js,ts,jsx,tsx,mdx}", - ], - theme: { - extend: { - colors: { - primary: "#ff9900", - secondary: "#1a140b", - }, - }, - }, - safelist: [ - "grid-cols-4", - "grid-cols-3", - "grid-cols-2", - { - pattern: /bg-(red|blue|yellow|green)/u, - }, - ], - plugins: [], -} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..69d083f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "noEmit": true, + "noErrorTruncation": true, + "esModuleInterop": true, + "paths": { + "@rahoot/common/*": ["./packages/common/src/*"], + "@rahoot/socket/*": ["./packages/socket/src/*"], + "@rahoot/web/*": ["./packages/web/src/*"] + }, + "strict": true, + "strictNullChecks": true + } +} From 8bdb8f47ef29079947f45ebcb1159fb62515862f Mon Sep 17 00:00:00 2001 From: Ralex <95540504+Ralex91@users.noreply.github.com> Date: Sat, 18 Oct 2025 18:20:03 +0200 Subject: [PATCH 02/17] feat(reconnect): add reconnect for player & manager --- package.json | 2 +- packages/common/src/types/game/index.ts | 1 + packages/common/src/types/game/socket.ts | 20 +- packages/socket/src/index.ts | 93 ++--- packages/socket/src/services/game.ts | 333 +++++++++++------- packages/socket/src/utils/game.ts | 74 ++++ packages/socket/src/utils/inviteCode.ts | 14 - packages/web/package.json | 1 + packages/web/src/app/(auth)/manager/page.tsx | 6 +- packages/web/src/app/game/[gameId]/page.tsx | 42 ++- .../src/app/game/manager/[gameId]/page.tsx | 45 ++- .../web/src/components/game/GameWrapper.tsx | 13 +- .../web/src/components/game/join/Username.tsx | 8 +- .../src/components/game/states/Answers.tsx | 10 +- .../web/src/components/game/states/Room.tsx | 4 +- packages/web/src/contexts/socketProvider.tsx | 37 +- packages/web/src/stores/game.tsx | 44 --- packages/web/src/stores/manager.tsx | 35 ++ packages/web/src/stores/player.tsx | 39 +- packages/web/src/stores/question.tsx | 14 + packages/web/src/utils/createStatus.ts | 8 + pnpm-lock.yaml | 26 +- 22 files changed, 593 insertions(+), 276 deletions(-) create mode 100644 packages/socket/src/utils/game.ts delete mode 100644 packages/socket/src/utils/inviteCode.ts delete mode 100644 packages/web/src/stores/game.tsx create mode 100644 packages/web/src/stores/manager.tsx create mode 100644 packages/web/src/stores/question.tsx create mode 100644 packages/web/src/utils/createStatus.ts diff --git a/package.json b/package.json index eee3bf7..b5f5cf8 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "dotenv-cli": "^10.0.0", - "typescript": "^5.0.0" + "typescript": "^5.9.3" } } diff --git a/packages/common/src/types/game/index.ts b/packages/common/src/types/game/index.ts index 06698a8..a47afdf 100644 --- a/packages/common/src/types/game/index.ts +++ b/packages/common/src/types/game/index.ts @@ -1,5 +1,6 @@ export type Player = { id: string + clientId: string username: string points: number } diff --git a/packages/common/src/types/game/socket.ts b/packages/common/src/types/game/socket.ts index 5a83c1f..fb0d4e1 100644 --- a/packages/common/src/types/game/socket.ts +++ b/packages/common/src/types/game/socket.ts @@ -1,5 +1,5 @@ import { Server as ServerIO, Socket as SocketIO } from "socket.io" -import { Player, QuizzWithId } from "." +import { GameUpdateQuestion, Player, QuizzWithId } from "." import { Status, StatusDataMap } from "./status" export type Server = ServerIO @@ -21,6 +21,8 @@ export type MessageGameId = { } export interface ServerToClientEvents { + connect: () => void + // Game events "game:status": (data: { name: Status; data: StatusDataMap[Status] }) => void "game:successRoom": (data: string) => void @@ -33,9 +35,23 @@ export interface ServerToClientEvents { "game:reset": () => void "game:updateQuestion": (data: { current: number; total: number }) => void "game:playerAnswer": (count: number) => void + + // Player events + "player:successReconnect": (data: { + gameId: string + status: { name: Status; data: StatusDataMap[Status] } + player: { username: string; points: number } + currentQuestion: GameUpdateQuestion + }) => void "player:updateLeaderboard": (data: { leaderboard: Player[] }) => void // Manager events + "manager:successReconnect": (data: { + gameId: string + status: { name: Status; data: StatusDataMap[Status] } + players: Player[] + currentQuestion: GameUpdateQuestion + }) => void "manager:quizzList": (quizzList: QuizzWithId[]) => void "manager:gameCreated": (data: { gameId: string; inviteCode: string }) => void "manager:statusUpdate": (data: { @@ -52,6 +68,7 @@ export interface ClientToServerEvents { // Manager actions "game:create": (quizzId: string) => void "manager:auth": (password: string) => void + "manager:reconnect": (message: { gameId: string }) => void "manager:kickPlayer": ( message: MessageWithoutStatus<{ playerId: string }> ) => void @@ -63,6 +80,7 @@ export interface ClientToServerEvents { // Player actions "player:join": (inviteCode: string) => void "player:login": (message: MessageWithoutStatus<{ username: string }>) => void + "player:reconnect": (message: { gameId: string }) => void "player:selectedAnswer": ( message: MessageWithoutStatus<{ answerKey: number }> ) => void diff --git a/packages/socket/src/index.ts b/packages/socket/src/index.ts index cf051ba..d784de6 100644 --- a/packages/socket/src/index.ts +++ b/packages/socket/src/index.ts @@ -1,7 +1,12 @@ -import { Server, Socket } from "@rahoot/common/types/game/socket" +import { Server } from "@rahoot/common/types/game/socket" import env from "@rahoot/socket/env" import Config from "@rahoot/socket/services/config" import Game from "@rahoot/socket/services/game" +import { + findManagerGameByClientId, + findPlayerGameByClientId, + withGame, +} from "@rahoot/socket/utils/game" import { inviteCodeValidator } from "@rahoot/socket/utils/validator" import { Server as ServerIO } from "socket.io" @@ -14,35 +19,37 @@ const port = env.SOCKER_PORT || 3001 console.log(`Socket server running on port ${port}`) io.listen(Number(port)) -function withGame( - gameId: string | undefined, - socket: Socket, - games: Game[], - handler: (game: Game) => T -): T | void { - let game = null - - if (gameId) { - game = games.find((g) => g.gameId === gameId) - } else { - game = games.find( - (g) => - g.players.find((p) => p.id === socket.id) || g.managerId === socket.id - ) - } - - if (!game) { - socket.emit("game:errorMessage", "Game not found") - return - } - - return handler(game) -} - io.on("connection", (socket) => { console.log(`A user connected ${socket.id}`) console.log(socket.handshake.auth) + socket.on("player:reconnect", () => { + const game = findPlayerGameByClientId(socket.handshake.auth.clientId, games) + + if (game) { + game.reconnect(socket) + + return + } + + socket.emit("game:reset") + }) + + socket.on("manager:reconnect", () => { + const game = findManagerGameByClientId( + socket.handshake.auth.clientId, + games + ) + + if (game) { + game.reconnect(socket) + + return + } + + socket.emit("game:reset") + }) + socket.on("manager:auth", (password) => { try { const config = Config.game() @@ -121,14 +128,14 @@ io.on("connection", (socket) => { ) socket.on("manager:showLeaderboard", ({ gameId }) => - withGame(gameId, socket, games, (game) => game.showLeaderboard(socket)) + withGame(gameId, socket, games, (game) => game.showLeaderboard()) ) socket.on("disconnect", () => { console.log(`user disconnected ${socket.id}`) - const managerGame = games.find((g) => g.managerId === socket.id) + const managerGame = games.find((g) => g.manager.id === socket.id) - if (managerGame) { + if (managerGame && !managerGame.started) { console.log("Reset game (manager disconnected)") managerGame.abortCooldown() @@ -141,19 +148,21 @@ io.on("connection", (socket) => { const game = games.find((g) => g.players.some((p) => p.id === socket.id)) - if (game) { - const player = game.players.find((p) => p.id === socket.id) - - if (player) { - game.players = game.players.filter((p) => p.id !== socket.id) - - io.to(game.managerId).emit("manager:removePlayer", player.id) - io.to(game.gameId).emit("game:totalPlayers", game.players.length) - - console.log( - `Removed player ${player.username} from game ${game.gameId}` - ) - } + if (!game || game.started) { + return } + + const player = game.players.find((p) => p.id === socket.id) + + if (!player) { + return + } + + game.players = game.players.filter((p) => p.id !== socket.id) + + io.to(game.manager.id).emit("manager:removePlayer", player.id) + io.to(game.gameId).emit("game:totalPlayers", game.players.length) + + console.log(`Removed player ${player.username} from game ${game.gameId}`) }) }) diff --git a/packages/socket/src/services/game.ts b/packages/socket/src/services/game.ts index b66c68f..3e24428 100644 --- a/packages/socket/src/services/game.ts +++ b/packages/socket/src/services/game.ts @@ -1,18 +1,27 @@ import { Answer, Player, Quizz } from "@rahoot/common/types/game" import { Server, Socket } from "@rahoot/common/types/game/socket" -import { Status } from "@rahoot/common/types/game/status" -import createInviteCode from "@rahoot/socket/utils/inviteCode" +import { Status, StatusDataMap } from "@rahoot/common/types/game/status" +import { createInviteCode, timeToPoint } from "@rahoot/socket/utils/game" +import sleep from "@rahoot/socket/utils/sleep" import { v4 as uuid } from "uuid" -import sleep from "../utils/sleep" class Game { io: Server gameId: string - managerId: string + manager: { + id: string + clientId: string + } inviteCode: string started: boolean - status: Status + + lastBroadcastStatus: { name: Status; data: StatusDataMap[Status] } | null = + null + managerStatus: { name: Status; data: StatusDataMap[Status] } | null = null + playerStatus: Map = + new Map() + quizz: Quizz players: Player[] @@ -34,10 +43,17 @@ class Game { this.io = io this.gameId = uuid() - this.managerId = "" + this.manager = { + id: "", + clientId: "", + } this.inviteCode = "" this.started = false - this.status = Status.SHOW_START + + this.lastBroadcastStatus = null + this.managerStatus = null + this.playerStatus = new Map() + this.players = [] this.round = { @@ -53,7 +69,10 @@ class Game { const roomInvite = createInviteCode() this.inviteCode = roomInvite - this.managerId = socket.id + this.manager = { + id: socket.id, + clientId: socket.handshake.auth.clientId, + } this.quizz = quizz socket.join(this.gameId) @@ -67,25 +86,48 @@ class Game { ) } + broadcastStatus(status: T, data: StatusDataMap[T]) { + const statusData = { name: status, data } + this.lastBroadcastStatus = statusData + this.io.to(this.gameId).emit("game:status", statusData) + } + + sendStatus( + target: string, + status: T, + data: StatusDataMap[T] + ) { + const statusData = { name: status, data } + + if (this.manager.id === target) { + this.managerStatus = statusData + } else { + this.playerStatus.set(target, statusData) + } + + this.io.to(target).emit("game:status", statusData) + } + join(socket: Socket, username: string) { socket.join(this.gameId) const playerData = { id: socket.id, + clientId: socket.handshake.auth.clientId, username: username, points: 0, } this.players.push(playerData) - this.io.to(this.managerId).emit("manager:newPlayer", playerData) + this.io.to(this.manager.id).emit("manager:newPlayer", playerData) this.io.to(this.gameId).emit("game:totalPlayers", this.players.length) socket.emit("game:successJoin", this.gameId) } kickPlayer(socket: Socket, playerId: string) { - if (this.managerId !== socket.id) { + if (this.manager.id !== socket.id) { return } @@ -96,21 +138,97 @@ class Game { } this.players = this.players.filter((p) => p.id !== playerId) + this.playerStatus.delete(playerId) this.io.in(playerId).socketsLeave(this.gameId) this.io.to(player.id).emit("game:kick") - this.io.to(this.managerId).emit("manager:playerKicked", player.id) + this.io.to(this.manager.id).emit("manager:playerKicked", player.id) this.io.to(this.gameId).emit("game:totalPlayers", this.players.length) } + reconnect(socket: Socket) { + const clientId = socket.handshake.auth.clientId + const isManager = this.manager.clientId === clientId + + if (!isManager) { + const player = this.players.find((p) => p.clientId === clientId) + + if (!player) { + return false + } + } + + socket.join(this.gameId) + + const commonData = { + gameId: this.gameId, + started: this.started, + currentQuestion: { + current: this.round.currentQuestion, + total: this.quizz.questions.length, + }, + } + + if (isManager) { + this.manager.id = socket.id + + const status = this.managerStatus || + this.lastBroadcastStatus || { + name: Status.WAIT, + data: { text: "Waiting for players" }, + } + + socket.emit("manager:successReconnect", { + ...commonData, + status, + players: this.players, + }) + socket.emit("game:totalPlayers", this.players.length) + + console.log(`Manager reconnected to game ${this.inviteCode}`) + + return + } + + const player = this.players.find((p) => p.clientId === clientId)! + const oldSocketId = player.id + player.id = socket.id + + const status = this.playerStatus.get(oldSocketId) || + this.lastBroadcastStatus || { + name: Status.WAIT, + data: { text: "Waiting for players" }, + } + + if (this.playerStatus.has(oldSocketId)) { + const oldStatus = this.playerStatus.get(oldSocketId)! + this.playerStatus.delete(oldSocketId) + this.playerStatus.set(socket.id, oldStatus) + } + + socket.emit("player:successReconnect", { + ...commonData, + status, + player: { + username: player.username, + points: player.points, + }, + }) + socket.emit("game:totalPlayers", this.players.length) + console.log( + `Player ${player.username} reconnected to game ${this.inviteCode}` + ) + + return true + } + async startCooldown(seconds: number) { if (this.cooldown.active) { return } this.cooldown.active = true - let count = seconds - 1 return new Promise((resolve) => { @@ -119,10 +237,11 @@ class Game { this.cooldown.active = false clearInterval(cooldownTimeout) resolve() - } else { - this.io.to(this.gameId).emit("game:cooldown", count) - count -= 1 + return } + + this.io.to(this.gameId).emit("game:cooldown", count) + count -= 1 }, 1000) }) } @@ -134,7 +253,7 @@ class Game { } async start(socket: Socket) { - if (this.managerId !== socket.id) { + if (this.manager.id !== socket.id) { return } @@ -143,18 +262,15 @@ class Game { } this.started = true - this.io.to(this.gameId).emit("game:status", { - name: Status.SHOW_START, - data: { - time: 3, - subject: this.quizz.subject, - }, + + this.broadcastStatus(Status.SHOW_START, { + time: 3, + subject: this.quizz.subject, }) await sleep(3) this.io.to(this.gameId).emit("game:startCooldown") - await this.startCooldown(3) this.newRound() @@ -167,17 +283,16 @@ class Game { return } + this.playerStatus.clear() + this.io.to(this.gameId).emit("game:updateQuestion", { current: this.round.currentQuestion + 1, total: this.quizz.questions.length, }) - this.io.to(this.gameId).emit("game:status", { - name: Status.SHOW_PREPARED, - data: { - totalAnswers: question.answers.length, - questionNumber: this.round.currentQuestion + 1, - }, + this.broadcastStatus(Status.SHOW_PREPARED, { + totalAnswers: question.answers.length, + questionNumber: this.round.currentQuestion + 1, }) await sleep(2) @@ -186,13 +301,10 @@ class Game { return } - this.io.to(this.gameId).emit("game:status", { - name: Status.SHOW_QUESTION, - data: { - question: question.question, - image: question.image, - cooldown: question.cooldown, - }, + this.broadcastStatus(Status.SHOW_QUESTION, { + question: question.question, + image: question.image, + cooldown: question.cooldown, }) await sleep(question.cooldown) @@ -203,15 +315,12 @@ class Game { this.round.startTime = Date.now() - this.io.to(this.gameId).emit("game:status", { - name: Status.SELECT_ANSWER, - data: { - question: question.question, - answers: question.answers, - image: question.image, - time: question.time, - totalPlayer: this.players.length, - }, + this.broadcastStatus(Status.SELECT_ANSWER, { + question: question.question, + answers: question.answers, + image: question.image, + time: question.time, + totalPlayer: this.players.length, }) await this.startCooldown(question.time) @@ -220,42 +329,10 @@ class Game { return } - this.players = this.players.map((player) => { - const playerAnswer = this.round.playersAnswers.find( - (a) => a.playerId === player.id - ) - - const isCorrect = playerAnswer - ? playerAnswer.answerId === question.solution - : false - - const points = - playerAnswer && isCorrect - ? Math.round(playerAnswer && playerAnswer.points) - : 0 - - player.points += points - - const sortPlayers = this.players.sort((a, b) => b.points - a.points) - - const rank = sortPlayers.findIndex((p) => p.id === player.id) + 1 - const aheadPlayer = sortPlayers[rank - 2] - - this.io.to(player.id).emit("game:status", { - name: Status.SHOW_RESULT, - data: { - correct: isCorrect, - message: isCorrect ? "Nice !" : "Too bad", - points, - myPoints: player.points, - rank, - aheadOfMe: aheadPlayer ? aheadPlayer.username : null, - }, - }) - - return player - }) + await this.showResults(question) + } + async showResults(question: any) { const totalType = this.round.playersAnswers.reduce( (acc: Record, { answerId }) => { acc[answerId] = (acc[answerId] || 0) + 1 @@ -264,36 +341,54 @@ class Game { {} ) - // Manager - this.io.to(this.gameId).emit("game:status", { - name: Status.SHOW_RESPONSES, - data: { - question: question.question, - responses: totalType, - correct: question.solution, - answers: question.answers, - image: question.image, - }, + const sortedPlayers = this.players + .map((player) => { + const playerAnswer = this.round.playersAnswers.find( + (a) => a.playerId === player.id + ) + + const isCorrect = playerAnswer + ? playerAnswer.answerId === question.solution + : false + + const points = + playerAnswer && isCorrect ? Math.round(playerAnswer.points) : 0 + + player.points += points + + return { ...player, lastCorrect: isCorrect, lastPoints: points } + }) + .sort((a, b) => b.points - a.points) + + this.players = sortedPlayers + + sortedPlayers.forEach((player, index) => { + const rank = index + 1 + const aheadPlayer = sortedPlayers[index - 1] + + this.sendStatus(player.id, Status.SHOW_RESULT, { + correct: player.lastCorrect, + message: player.lastCorrect ? "Nice!" : "Too bad", + points: player.lastPoints, + myPoints: player.points, + rank, + aheadOfMe: aheadPlayer ? aheadPlayer.username : null, + }) + }) + + this.sendStatus(this.manager.id, Status.SHOW_RESPONSES, { + question: question.question, + responses: totalType, + correct: question.solution, + answers: question.answers, + image: question.image, }) this.round.playersAnswers = [] } - timeToPoint(startTime: number, secondes: number) { - let points = 1000 - - const actualTime = Date.now() - const tempsPasseEnSecondes = (actualTime - startTime) / 1000 - - points -= (1000 / secondes) * tempsPasseEnSecondes - points = Math.max(0, points) - - return points - } - async selectAnswer(socket: Socket, answerId: number) { const player = this.players.find((player) => player.id === socket.id) - const question = this.quizz.questions[this.round.currentQuestion] if (!player) { @@ -307,13 +402,13 @@ class Game { this.round.playersAnswers.push({ playerId: player.id, answerId, - points: this.timeToPoint(this.round.startTime, question.time), + points: timeToPoint(this.round.startTime, question.time), }) - socket.emit("game:status", { - name: Status.WAIT, - data: { text: "Waiting for the players to answer" }, + this.sendStatus(socket.id, Status.WAIT, { + text: "Waiting for the players to answer", }) + socket .to(this.gameId) .emit("game:playerAnswer", this.round.playersAnswers.length) @@ -330,7 +425,7 @@ class Game { return } - if (socket.id !== this.managerId) { + if (socket.id !== this.manager.id) { return } @@ -347,36 +442,32 @@ class Game { return } - if (socket.id !== this.managerId) { + if (socket.id !== this.manager.id) { return } this.abortCooldown() } - showLeaderboard(socket: Socket) { + showLeaderboard() { const isLastRound = this.round.currentQuestion + 1 === this.quizz.questions.length const sortedPlayers = this.players.sort((a, b) => b.points - a.points) if (isLastRound) { - socket.emit("game:status", { - name: Status.FINISHED, - data: { - subject: this.quizz.subject, - top: sortedPlayers.slice(0, 3), - }, + this.started = false + + this.broadcastStatus(Status.FINISHED, { + subject: this.quizz.subject, + top: sortedPlayers.slice(0, 3), }) return } - socket.emit("game:status", { - name: Status.SHOW_LEADERBOARD, - data: { - leaderboard: sortedPlayers.slice(0, 5), - }, + this.sendStatus(this.manager.id, Status.SHOW_LEADERBOARD, { + leaderboard: sortedPlayers.slice(0, 5), }) } } diff --git a/packages/socket/src/utils/game.ts b/packages/socket/src/utils/game.ts new file mode 100644 index 0000000..9a7f92a --- /dev/null +++ b/packages/socket/src/utils/game.ts @@ -0,0 +1,74 @@ +import { Socket } from "@rahoot/common/types/game/socket" +import Game from "@rahoot/socket/services/game" + +export const withGame = ( + gameId: string | undefined, + socket: Socket, + games: Game[], + handler: (game: Game) => T +): T | void => { + let game = null + + if (gameId) { + game = games.find((g) => g.gameId === gameId) + } else { + game = games.find( + (g) => + g.players.find((p) => p.id === socket.id) || g.manager.id === socket.id + ) + } + + if (!game) { + socket.emit("game:errorMessage", "Game not found") + return + } + + return handler(game) +} + +export const createInviteCode = (length = 6) => { + let result = "" + const characters = "0123456789" + const charactersLength = characters.length + + for (let i = 0; i < length; i += 1) { + const randomIndex = Math.floor(Math.random() * charactersLength) + result += characters.charAt(randomIndex) + } + + return result +} + +export const timeToPoint = (startTime: number, secondes: number): number => { + let points = 1000 + + const actualTime = Date.now() + const tempsPasseEnSecondes = (actualTime - startTime) / 1000 + + points -= (1000 / secondes) * tempsPasseEnSecondes + points = Math.max(0, points) + + return points +} + +export const findPlayerGameByClientId = (clientId: string, games: Game[]) => { + const playerGame = games.find((g) => + g.players.find((p) => p.clientId === clientId) + ) + + if (playerGame) { + return playerGame + } + + return null +} + +export const findManagerGameByClientId = (clientId: string, games: Game[]) => { + const managerGame = games.find((g) => g.manager.clientId === clientId) + + if (managerGame) { + return managerGame + } + + return null +} diff --git a/packages/socket/src/utils/inviteCode.ts b/packages/socket/src/utils/inviteCode.ts deleted file mode 100644 index f6837ee..0000000 --- a/packages/socket/src/utils/inviteCode.ts +++ /dev/null @@ -1,14 +0,0 @@ -const createInviteCode = (length = 6) => { - let result = "" - const characters = "0123456789" - const charactersLength = characters.length - - for (let i = 0; i < length; i += 1) { - const randomIndex = Math.floor(Math.random() * charactersLength) - result += characters.charAt(randomIndex) - } - - return result -} - -export default createInviteCode diff --git a/packages/web/package.json b/packages/web/package.json index 71aca3e..7fa8e4c 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -20,6 +20,7 @@ "react-hot-toast": "^2.6.0", "socket.io-client": "^4.8.1", "use-sound": "^5.0.0", + "uuid": "^13.0.0", "yup": "^1.7.1", "zod": "^4.1.12", "zustand": "^5.0.8" diff --git a/packages/web/src/app/(auth)/manager/page.tsx b/packages/web/src/app/(auth)/manager/page.tsx index 507b27d..63b63a0 100644 --- a/packages/web/src/app/(auth)/manager/page.tsx +++ b/packages/web/src/app/(auth)/manager/page.tsx @@ -4,12 +4,12 @@ import { QuizzWithId } from "@rahoot/common/types/game" import ManagerPassword from "@rahoot/web/components/game/create/ManagerPassword" import SelectQuizz from "@rahoot/web/components/game/create/SelectQuizz" import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" -import { useManagerGameStore } from "@rahoot/web/stores/game" +import { useManagerStore } from "@rahoot/web/stores/manager" import { useRouter } from "next/navigation" import { useState } from "react" export default function Manager() { - const { setStatus } = useManagerGameStore() + const { setGameId, setStatus } = useManagerStore() const router = useRouter() const { socket } = useSocket() @@ -22,6 +22,7 @@ export default function Manager() { }) useEvent("manager:gameCreated", ({ gameId, inviteCode }) => { + setGameId(gameId) setStatus("SHOW_ROOM", { text: "Waiting for the players", inviteCode }) router.push(`/game/manager/${gameId}`) }) @@ -32,7 +33,6 @@ export default function Manager() { const handleCreate = (quizzId: string) => { console.log(quizzId) socket?.emit("game:create", quizzId) - console.log("create room") } if (!isAuth) { diff --git a/packages/web/src/app/game/[gameId]/page.tsx b/packages/web/src/app/game/[gameId]/page.tsx index ad6907e..6bcd0b9 100644 --- a/packages/web/src/app/game/[gameId]/page.tsx +++ b/packages/web/src/app/game/[gameId]/page.tsx @@ -8,24 +8,36 @@ import Question from "@rahoot/web/components/game/states/Question" import Result from "@rahoot/web/components/game/states/Result" import Start from "@rahoot/web/components/game/states/Start" import Wait from "@rahoot/web/components/game/states/Wait" -import { useEvent } from "@rahoot/web/contexts/socketProvider" -import { usePlayerGameStore } from "@rahoot/web/stores/game" +import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" import { usePlayerStore } from "@rahoot/web/stores/player" +import { useQuestionStore } from "@rahoot/web/stores/question" import { GAME_STATE_COMPONENTS } from "@rahoot/web/utils/constants" -import { useRouter } from "next/navigation" -import { useEffect } from "react" +import { useParams, useRouter } from "next/navigation" import toast from "react-hot-toast" export default function Game() { const router = useRouter() - const { player, logout } = usePlayerStore() - const { status, setStatus, resetStatus } = usePlayerGameStore() + const { socket, isConnected } = useSocket() + const { gameId: gameIdParam }: { gameId?: string } = useParams() + const { status, setPlayer, logout, setGameId, setStatus, resetStatus } = + usePlayerStore() + const { setQuestionStates } = useQuestionStore() - useEffect(() => { - if (!player) { - router.replace("/") + useEvent("connect", () => { + if (gameIdParam) { + socket?.emit("player:reconnect", { gameId: gameIdParam }) } - }, [player, router]) + }) + + useEvent( + "player:successReconnect", + ({ gameId, status, player, currentQuestion }) => { + setGameId(gameId) + setStatus(status.name, status.data) + setPlayer(player) + setQuestionStates(currentQuestion) + }, + ) useEvent("game:status", ({ name, data }) => { if (name in GAME_STATE_COMPONENTS) { @@ -35,11 +47,19 @@ export default function Game() { useEvent("game:reset", () => { router.replace("/") - logout() resetStatus() + logout() toast("The game has been reset by the host") }) + if (!isConnected) { + return null + } + + if (!gameIdParam) { + return null + } + let component = null switch (status.name) { diff --git a/packages/web/src/app/game/manager/[gameId]/page.tsx b/packages/web/src/app/game/manager/[gameId]/page.tsx index 7d457d8..67cf094 100644 --- a/packages/web/src/app/game/manager/[gameId]/page.tsx +++ b/packages/web/src/app/game/manager/[gameId]/page.tsx @@ -11,16 +11,20 @@ import Responses from "@rahoot/web/components/game/states/Responses" import Room from "@rahoot/web/components/game/states/Room" import Start from "@rahoot/web/components/game/states/Start" import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" -import { useManagerGameStore } from "@rahoot/web/stores/game" +import { useManagerStore } from "@rahoot/web/stores/manager" +import { useQuestionStore } from "@rahoot/web/stores/question" import { GAME_STATE_COMPONENTS_MANAGER } from "@rahoot/web/utils/constants" -import { useParams } from "next/navigation" +import { useParams, useRouter } from "next/navigation" import { useEffect, useState } from "react" +import toast from "react-hot-toast" export default function ManagerGame() { - const { socket } = useSocket() + const router = useRouter() + const { gameId: gameIdParam }: { gameId?: string } = useParams() + const { socket, isConnected } = useSocket() const [nextText, setNextText] = useState("Start") - const { status, setStatus } = useManagerGameStore() - const { gameId }: { gameId?: string } = useParams() + const { gameId, status, setGameId, setStatus, setPlayers } = useManagerStore() + const { setQuestionStates } = useQuestionStore() useEvent("game:status", ({ name, data }) => { if (name in GAME_STATE_COMPONENTS_MANAGER) { @@ -28,12 +32,41 @@ export default function ManagerGame() { } }) + useEvent("connect", () => { + if (gameIdParam) { + socket?.emit("manager:reconnect", { gameId: gameIdParam }) + } + }) + + useEvent( + "manager:successReconnect", + ({ gameId, status, players, currentQuestion }) => { + setGameId(gameId) + setStatus(status.name, status.data) + setPlayers(players) + setQuestionStates(currentQuestion) + }, + ) + + useEvent("game:reset", () => { + router.replace("/manager") + toast("Game is not available anymore") + }) + useEffect(() => { - if (status.name === "SHOW_START") { + if (status.name === Status.SHOW_START) { setNextText("Start") } }, [status.name]) + if (!isConnected) { + return null + } + + if (!gameId) { + return null + } + const handleSkip = () => { setNextText("Skip") diff --git a/packages/web/src/components/game/GameWrapper.tsx b/packages/web/src/components/game/GameWrapper.tsx index be74569..225b9ea 100644 --- a/packages/web/src/components/game/GameWrapper.tsx +++ b/packages/web/src/components/game/GameWrapper.tsx @@ -1,13 +1,13 @@ "use client" -import { GameUpdateQuestion } from "@rahoot/common/types/game" import background from "@rahoot/web/assets/background.webp" import Button from "@rahoot/web/components/Button" import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" import { usePlayerStore } from "@rahoot/web/stores/player" +import { useQuestionStore } from "@rahoot/web/stores/question" import Image from "next/image" import { useRouter } from "next/navigation" -import { PropsWithChildren, useEffect, useState } from "react" +import { PropsWithChildren, useEffect } from "react" type Props = PropsWithChildren & { textNext?: string @@ -23,10 +23,9 @@ export default function GameWrapper({ }: Props) { const { isConnected, connect } = useSocket() const { player, logout } = usePlayerStore() + const { questionStates, setQuestionStates } = useQuestionStore() const router = useRouter() - const [questionState, setQuestionState] = useState() - useEffect(() => { if (!isConnected) { connect() @@ -39,7 +38,7 @@ export default function GameWrapper({ }) useEvent("game:updateQuestion", ({ current, total }) => { - setQuestionState({ + setQuestionStates({ current, total, }) @@ -56,9 +55,9 @@ export default function GameWrapper({
- {questionState && ( + {questionStates && (
- {`${questionState.current} / ${questionState.total}`} + {`${questionStates.current} / ${questionStates.total}`}
)} diff --git a/packages/web/src/components/game/join/Username.tsx b/packages/web/src/components/game/join/Username.tsx index 9425c19..4567cb2 100644 --- a/packages/web/src/components/game/join/Username.tsx +++ b/packages/web/src/components/game/join/Username.tsx @@ -11,12 +11,16 @@ import { KeyboardEvent, useState } from "react" export default function Username() { const { socket } = useSocket() - const { player, login } = usePlayerStore() + const { gameId, login } = usePlayerStore() const router = useRouter() const [username, setUsername] = useState("") const handleLogin = () => { - socket?.emit("player:login", { gameId: player?.gameId, data: { username } }) + if (!gameId) { + return + } + + socket?.emit("player:login", { gameId, data: { username } }) } const handleKeyDown = (event: KeyboardEvent) => { diff --git a/packages/web/src/components/game/states/Answers.tsx b/packages/web/src/components/game/states/Answers.tsx index f906c99..f8d1253 100644 --- a/packages/web/src/components/game/states/Answers.tsx +++ b/packages/web/src/components/game/states/Answers.tsx @@ -33,9 +33,10 @@ export default function Answers({ volume: 0.1, }) - const [playMusic] = useSound(SFX_ANSWERS_MUSIC, { + const [playMusic, { stop: stopMusic }] = useSound(SFX_ANSWERS_MUSIC, { volume: 0.2, interrupt: true, + loop: true, }) const handleAnswer = (answerKey: number) => () => { @@ -53,9 +54,12 @@ export default function Answers({ } useEffect(() => { - console.log("play music") playMusic() - }, []) + + return () => { + stopMusic() + } + }, [playMusic]) useEvent("game:cooldown", (sec) => { setCooldown(sec) diff --git a/packages/web/src/components/game/states/Room.tsx b/packages/web/src/components/game/states/Room.tsx index 0190347..533dcdb 100644 --- a/packages/web/src/components/game/states/Room.tsx +++ b/packages/web/src/components/game/states/Room.tsx @@ -3,6 +3,7 @@ import { Player } from "@rahoot/common/types/game" import { ManagerStatusDataMap } from "@rahoot/common/types/game/status" import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" +import { useManagerStore } from "@rahoot/web/stores/manager" import { useState } from "react" type Props = { @@ -11,7 +12,8 @@ type Props = { export default function Room({ data: { text, inviteCode } }: Props) { const { socket } = useSocket() - const [playerList, setPlayerList] = useState([]) + const { players } = useManagerStore() + const [playerList, setPlayerList] = useState(players) const [totalPlayers, setTotalPlayers] = useState(0) useEvent("manager:newPlayer", (player) => { diff --git a/packages/web/src/contexts/socketProvider.tsx b/packages/web/src/contexts/socketProvider.tsx index 24d8a6e..7451e48 100644 --- a/packages/web/src/contexts/socketProvider.tsx +++ b/packages/web/src/contexts/socketProvider.tsx @@ -1,5 +1,6 @@ /* eslint-disable no-empty-function */ "use client" + import { ClientToServerEvents, ServerToClientEvents, @@ -13,12 +14,14 @@ import React, { useState, } from "react" import { io, Socket } from "socket.io-client" +import { v7 as uuid } from "uuid" type TypedSocket = Socket interface SocketContextValue { socket: TypedSocket | null isConnected: boolean + clientId: string connect: () => void disconnect: () => void reconnect: () => void @@ -27,6 +30,7 @@ interface SocketContextValue { const SocketContext = createContext({ socket: null, isConnected: false, + clientId: "", connect: () => {}, disconnect: () => {}, reconnect: () => {}, @@ -38,11 +42,33 @@ const getSocketServer = async () => { return res.url } +const getClientId = (): string => { + try { + const stored = localStorage.getItem("client_id") + + if (stored) { + return stored + } + + const newId = uuid() + localStorage.setItem("client_id", newId) + + return newId + } catch { + return uuid() + } +} + export const SocketProvider = ({ children }: { children: React.ReactNode }) => { const [socket, setSocket] = useState(null) const [isConnected, setIsConnected] = useState(false) + const [clientId] = useState(() => getClientId()) useEffect(() => { + if (socket) { + return + } + let s: TypedSocket | null = null const initSocket = async () => { @@ -52,6 +78,9 @@ export const SocketProvider = ({ children }: { children: React.ReactNode }) => { s = io(socketUrl, { transports: ["websocket"], autoConnect: false, + auth: { + clientId, + }, }) setSocket(s) @@ -61,7 +90,6 @@ export const SocketProvider = ({ children }: { children: React.ReactNode }) => { }) s.on("disconnect", () => { - console.log("Socket disconnected") setIsConnected(false) }) @@ -75,28 +103,26 @@ export const SocketProvider = ({ children }: { children: React.ReactNode }) => { initSocket() + // eslint-disable-next-line consistent-return return () => { s?.disconnect() } - }, []) + }, [clientId]) const connect = useCallback(() => { if (socket && !socket.connected) { - console.log("🔌 Manual connect") socket.connect() } }, [socket]) const disconnect = useCallback(() => { if (socket && socket.connected) { - console.log("🧹 Manual disconnect") socket.disconnect() } }, [socket]) const reconnect = useCallback(() => { if (socket) { - console.log("♻️ Manual reconnect") socket.disconnect() socket.connect() } @@ -107,6 +133,7 @@ export const SocketProvider = ({ children }: { children: React.ReactNode }) => { value={{ socket, isConnected, + clientId, connect, disconnect, reconnect, diff --git a/packages/web/src/stores/game.tsx b/packages/web/src/stores/game.tsx deleted file mode 100644 index 2d22aac..0000000 --- a/packages/web/src/stores/game.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { StatusDataMap } from "@rahoot/common/types/game/status" -import { create } from "zustand" - -export type Status = { - [K in keyof T]: { name: K; data: T[K] } -}[keyof T] - -export function createStatus( - name: K, - data: T[K], -): Status { - return { name, data } -} - -type GameStore = { - status: Status - // eslint-disable-next-line no-unused-vars - setStatus: (name: K, data: T[K]) => void - resetStatus: () => void -} - -export const usePlayerGameStore = create>((set) => { - const initialStatus = createStatus("WAIT", { - text: "Waiting for the players", - }) - - return { - status: initialStatus, - setStatus: (name, data) => set({ status: createStatus(name, data) }), - resetStatus: () => set({ status: initialStatus }), - } -}) - -export const useManagerGameStore = create>((set) => { - const initialStatus = createStatus("SHOW_ROOM", { - text: "Waiting for the players", - }) - - return { - status: initialStatus, - setStatus: (name, data) => set({ status: createStatus(name, data) }), - resetStatus: () => set({ status: initialStatus }), - } -}) diff --git a/packages/web/src/stores/manager.tsx b/packages/web/src/stores/manager.tsx new file mode 100644 index 0000000..0699dbd --- /dev/null +++ b/packages/web/src/stores/manager.tsx @@ -0,0 +1,35 @@ +/* eslint-disable no-unused-vars */ +import { Player } from "@rahoot/common/types/game" +import { StatusDataMap } from "@rahoot/common/types/game/status" +import { createStatus, Status } from "@rahoot/web/utils/createStatus" +import { create } from "zustand" + +type ManagerStore = { + gameId: string | null + status: Status + players: Player[] + + setGameId: (gameId: string | null) => void + + setStatus: (name: K, data: T[K]) => void + resetStatus: () => void + + setPlayers: (players: Player[]) => void +} + +const initialStatus = createStatus("SHOW_ROOM", { + text: "Waiting for the players", +}) + +export const useManagerStore = create>((set) => ({ + gameId: null, + status: initialStatus, + players: [], + + setGameId: (gameId) => set({ gameId }), + + setStatus: (name, data) => set({ status: createStatus(name, data) }), + resetStatus: () => set({ status: initialStatus }), + + setPlayers: (players) => set({ players }), +})) diff --git a/packages/web/src/stores/player.tsx b/packages/web/src/stores/player.tsx index 9f9b046..2517947 100644 --- a/packages/web/src/stores/player.tsx +++ b/packages/web/src/stores/player.tsx @@ -1,32 +1,54 @@ /* eslint-disable no-unused-vars */ +import { StatusDataMap } from "@rahoot/common/types/game/status" +import { createStatus, Status } from "@rahoot/web/utils/createStatus" import { create } from "zustand" type PlayerState = { - gameId?: string username?: string points?: number } -type PlayerStore = { +type PlayerStore = { + gameId: string | null player: PlayerState | null + status: Status + + setGameId: (gameId: string | null) => void + + setPlayer: (state: PlayerState) => void login: (gameId: string) => void join: (username: string) => void updatePoints: (points: number) => void logout: () => void + + setStatus: (name: K, data: T[K]) => void + resetStatus: () => void } -export const usePlayerStore = create((set) => ({ - player: null, +const initialStatus = createStatus("WAIT", { + text: "Waiting for the players", +}) +export const usePlayerStore = create>((set) => ({ + gameId: null, + player: null, + status: initialStatus, + currentQuestion: null, + + setGameId: (gameId) => set({ gameId }), + + setPlayer: (player: PlayerState) => set({ player }), login: (username) => set((state) => ({ player: { ...state.player, username }, })), - join: (gameId) => + join: (gameId) => { set((state) => ({ - player: { ...state.player, gameId, points: 0 }, - })), + gameId, + player: { ...state.player, points: 0 }, + })) + }, updatePoints: (points) => set((state) => ({ @@ -34,4 +56,7 @@ export const usePlayerStore = create((set) => ({ })), logout: () => set({ player: null }), + + setStatus: (name, data) => set({ status: createStatus(name, data) }), + resetStatus: () => set({ status: initialStatus }), })) diff --git a/packages/web/src/stores/question.tsx b/packages/web/src/stores/question.tsx new file mode 100644 index 0000000..6180ee3 --- /dev/null +++ b/packages/web/src/stores/question.tsx @@ -0,0 +1,14 @@ +/* eslint-disable no-unused-vars */ +import { GameUpdateQuestion } from "@rahoot/common/types/game" +import { create } from "zustand" + +type QuestionStore = { + questionStates: GameUpdateQuestion | null + setQuestionStates: (state: GameUpdateQuestion) => void +} + +export const useQuestionStore = create((set) => ({ + questionStates: null, + setQuestionStates: (state: GameUpdateQuestion) => + set({ questionStates: state }), +})) diff --git a/packages/web/src/utils/createStatus.ts b/packages/web/src/utils/createStatus.ts new file mode 100644 index 0000000..8c9dba4 --- /dev/null +++ b/packages/web/src/utils/createStatus.ts @@ -0,0 +1,8 @@ +export type Status = { + [K in keyof T]: { name: K; data: T[K] } +}[keyof T] + +export const createStatus = ( + name: K, + data: T[K], +): Status => ({ name, data }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6804027..4cb3b04 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^10.0.0 version: 10.0.0 typescript: - specifier: ^5.0.0 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 packages/common: dependencies: @@ -38,7 +38,7 @@ importers: version: link:../common '@t3-oss/env-core': specifier: ^0.13.8 - version: 0.13.8(typescript@5.9.2)(zod@4.1.11) + version: 0.13.8(typescript@5.9.3)(zod@4.1.11) socket.io: specifier: ^4.8.1 version: 4.8.1 @@ -94,6 +94,9 @@ importers: use-sound: specifier: ^5.0.0 version: 5.0.0(react@19.1.0) + uuid: + specifier: ^13.0.0 + version: 13.0.0 yup: specifier: ^1.7.1 version: 1.7.1 @@ -2360,6 +2363,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -2906,16 +2914,16 @@ snapshots: dependencies: tslib: 2.8.1 - '@t3-oss/env-core@0.13.8(typescript@5.9.2)(zod@4.1.11)': - optionalDependencies: - typescript: 5.9.2 - zod: 4.1.11 - '@t3-oss/env-core@0.13.8(typescript@5.9.2)(zod@4.1.12)': optionalDependencies: typescript: 5.9.2 zod: 4.1.12 + '@t3-oss/env-core@0.13.8(typescript@5.9.3)(zod@4.1.11)': + optionalDependencies: + typescript: 5.9.3 + zod: 4.1.11 + '@t3-oss/env-nextjs@0.13.8(typescript@5.9.2)(zod@4.1.12)': dependencies: '@t3-oss/env-core': 0.13.8(typescript@5.9.2)(zod@4.1.12) @@ -4779,6 +4787,8 @@ snapshots: typescript@5.9.2: {} + typescript@5.9.3: {} + unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 From 96bff164c0777c211488eb45b7807671d64c3096 Mon Sep 17 00:00:00 2001 From: Ralex <95540504+Ralex91@users.noreply.github.com> Date: Sun, 19 Oct 2025 00:37:26 +0200 Subject: [PATCH 03/17] feat: improve reconnect, add ESLint configuration for common and socket --- Dockerfile | 6 + package.json | 3 +- packages/common/eslint.config.mjs | 208 +++++ packages/common/package.json | 13 +- packages/common/src/types/game/socket.ts | 60 +- packages/common/src/types/game/status.ts | 33 +- .../src/validators/auth.ts} | 0 packages/common/tsconfig.json | 1 + packages/config/game.json | 4 + packages/config/quizz/example.json | 41 + packages/socket/eslint.config.mjs | 208 +++++ packages/socket/package.json | 11 +- packages/socket/src/index.ts | 79 +- packages/socket/src/services/config.ts | 18 +- packages/socket/src/services/game.ts | 46 +- packages/socket/src/services/registry.ts | 158 ++++ packages/socket/src/utils/game.ts | 55 +- packages/socket/tsconfig.json | 1 + packages/web/eslint.config.mjs | 21 +- packages/web/package.json | 21 +- packages/web/src/app/(auth)/layout.tsx | 32 +- packages/web/src/app/(auth)/manager/page.tsx | 1 - packages/web/src/app/(auth)/page.tsx | 17 +- packages/web/src/app/game/[gameId]/page.tsx | 35 +- .../src/app/game/manager/[gameId]/page.tsx | 55 +- packages/web/src/app/globals.css | 5 + packages/web/src/components/Loader.tsx | 10 +- .../web/src/components/game/GameWrapper.tsx | 86 +- .../game/create/ManagerPassword.tsx | 32 +- .../components/game/create/SelectQuizz.tsx | 61 +- .../web/src/components/icons/Pentagon.tsx | 4 +- packages/web/src/stores/manager.tsx | 17 +- packages/web/src/stores/player.tsx | 29 +- packages/web/src/stores/question.tsx | 3 +- packages/web/src/utils/constants.ts | 37 +- pnpm-lock.yaml | 837 +++++++++++------- 36 files changed, 1571 insertions(+), 677 deletions(-) create mode 100644 packages/common/eslint.config.mjs rename packages/{socket/src/utils/validator.ts => common/src/validators/auth.ts} (100%) create mode 100644 packages/config/game.json create mode 100644 packages/config/quizz/example.json create mode 100644 packages/socket/eslint.config.mjs create mode 100644 packages/socket/src/services/registry.ts diff --git a/Dockerfile b/Dockerfile index 974acca..cb58f84 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,6 +27,9 @@ RUN pnpm install --frozen-lockfile # Build Next.js app with standalone output for smaller runtime image WORKDIR /app/packages/web + +ENV NEXT_TELEMETRY_DISABLED=1 + RUN pnpm build # Build socket server if needed (TypeScript or similar) @@ -56,6 +59,9 @@ COPY --from=builder /app/packages/web/public ./packages/web/public # Copy the socket server build COPY --from=builder /app/packages/socket/dist ./packages/socket/dist +# Copy the game default config +COPY --from=builder /app/config ./config + # Expose the web and socket ports EXPOSE 3000 5505 diff --git a/package.json b/package.json index b5f5cf8..e173a4a 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev:socket": "dotenv -e .env -- pnpm --filter socket dev", "build": "pnpm -r run build", "start": "pnpm -r --parallel run start", - "clean": "pnpm -r exec rm -rf dist node_modules" + "clean": "pnpm -r exec rm -rf dist node_modules", + "lint": "pnpm -r run lint" }, "devDependencies": { "dotenv-cli": "^10.0.0", diff --git a/packages/common/eslint.config.mjs b/packages/common/eslint.config.mjs new file mode 100644 index 0000000..648d4db --- /dev/null +++ b/packages/common/eslint.config.mjs @@ -0,0 +1,208 @@ +import js from "@eslint/js" +import { defineConfig } from "eslint/config" +import globals from "globals" +import tseslint from "typescript-eslint" + +export default defineConfig([ + { + ignores: ["**/node_modules/**"], + }, + { + files: ["**/*.ts"], + languageOptions: { + ...js.configs.recommended.languageOptions, + parser: tseslint.parser, + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + globals: { + ...globals.node, + }, + }, + plugins: { + "@typescript-eslint": tseslint.plugin, + }, + rules: { + ...js.configs.recommended.rules, + ...tseslint.configs.recommendedTypeChecked[0].rules, + + "array-callback-return": [ + "error", + { allowImplicit: false, checkForEach: true, allowVoid: true }, + ], + "no-await-in-loop": "error", + "no-constant-binary-expression": "error", + "no-constructor-return": "error", + "no-duplicate-imports": ["error", { includeExports: true }], + "no-new-native-nonconstructor": "error", + "no-promise-executor-return": ["error", { allowVoid: true }], + "no-self-compare": "error", + "no-template-curly-in-string": "error", + "no-unmodified-loop-condition": "error", + "no-unreachable-loop": "error", + "no-unused-private-class-members": "error", + "arrow-body-style": ["error", "as-needed"], + camelcase: [ + "error", + { + properties: "always", + ignoreDestructuring: true, + ignoreImports: true, + ignoreGlobals: true, + }, + ], + "capitalized-comments": [ + "error", + "always", + { ignoreConsecutiveComments: true }, + ], + "class-methods-use-this": ["error", { enforceForClassFields: true }], + complexity: ["warn", 40], + "consistent-return": "error", + curly: ["error", "all"], + "default-param-last": "error", + "dot-notation": "error", + eqeqeq: ["error", "always"], + "func-name-matching": "error", + "func-names": "error", + "func-style": ["error", "declaration", { allowArrowFunctions: true }], + "grouped-accessor-pairs": ["error", "getBeforeSet"], + "guard-for-in": "error", + "init-declarations": ["error", "always"], + "logical-assignment-operators": [ + "error", + "always", + { enforceForIfStatements: true }, + ], + "max-classes-per-file": ["error", { ignoreExpressions: true }], + "max-depth": ["error", 3], + "max-lines": [ + "error", + { max: 500, skipBlankLines: true, skipComments: true }, + ], + "max-nested-callbacks": ["error", 3], + "max-params": ["error", 4], + "multiline-comment-style": ["error", "separate-lines"], + "no-alert": "error", + "no-bitwise": "error", + "no-caller": "error", + "no-else-return": "error", + "no-empty-function": "error", + "no-empty-static-block": "error", + "no-eq-null": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-label": "error", + "no-implicit-coercion": "error", + "no-implicit-globals": "error", + "no-implied-eval": "error", + "no-inline-comments": "error", + "no-invalid-this": "error", + "no-iterator": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-lonely-if": "error", + "no-loop-func": "error", + "no-multi-assign": "error", + "no-multi-str": "error", + "no-nested-ternary": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-object-constructor": "error", + "no-octal-escape": "error", + "no-param-reassign": "error", + "no-plusplus": "error", + "no-proto": "error", + "no-return-assign": ["error", "always"], + "no-script-url": "error", + "no-sequences": "error", + "no-throw-literal": "error", + "no-undef-init": "error", + "no-unneeded-ternary": ["error", { defaultAssignment: false }], + "no-unused-expressions": ["error", { enforceForJSX: true }], + "no-unused-vars": ["error", { argsIgnorePattern: "^_" }], + "no-useless-call": "error", + "no-useless-computed-key": ["error", { enforceForClassMembers: true }], + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-var": "error", + "no-warning-comments": ["error", { terms: ["todo"] }], + "object-shorthand": ["error", "always"], + "one-var": ["error", "never"], + "operator-assignment": ["error", "always"], + "prefer-arrow-callback": "error", + "prefer-const": [ + "error", + { destructuring: "any", ignoreReadBeforeAssign: false }, + ], + "prefer-destructuring": "error", + "prefer-exponentiation-operator": "error", + "prefer-numeric-literals": "error", + "prefer-object-has-own": "error", + "prefer-object-spread": "error", + "prefer-promise-reject-errors": "error", + "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }], + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "error", + radix: "error", + "require-await": "error", + "require-unicode-regexp": "error", + "symbol-description": "error", + yoda: "error", + "line-comment-position": ["error", { position: "above" }], + indent: "off", + "newline-before-return": "error", + "no-undef": "error", + "padded-blocks": ["error", "never"], + "padding-line-between-statements": [ + "error", + { + blankLine: "always", + prev: "*", + next: [ + "break", + "case", + "cjs-export", + "class", + "continue", + "do", + "if", + "switch", + "try", + "while", + "return", + ], + }, + { + blankLine: "always", + prev: [ + "break", + "case", + "cjs-export", + "class", + "continue", + "do", + "if", + "switch", + "try", + "while", + "return", + ], + next: "*", + }, + ], + quotes: [ + "error", + "double", + { avoidEscape: true, allowTemplateLiterals: true }, + ], + "space-before-blocks": "error", + semi: ["error", "never"], + }, + }, +]) diff --git a/packages/common/package.json b/packages/common/package.json index be7ddc7..f9f4b6f 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -2,12 +2,19 @@ "name": "@rahoot/common", "version": "1.0.0", "type": "module", + "scripts": { + "lint": "eslint" + }, "dependencies": { "socket.io": "^4.8.1", - "zod": "^3.22.4" + "zod": "^3.25.76" }, "devDependencies": { - "@types/node": "^20.11.0", - "typescript": "^5.3.3" + "@eslint/js": "^9.38.0", + "@types/node": "^20.19.22", + "eslint": "^9.38.0", + "globals": "^16.4.0", + "typescript": "^5.9.3", + "typescript-eslint": "^8.46.1" } } diff --git a/packages/common/src/types/game/socket.ts b/packages/common/src/types/game/socket.ts index fb0d4e1..e0b5294 100644 --- a/packages/common/src/types/game/socket.ts +++ b/packages/common/src/types/game/socket.ts @@ -24,65 +24,65 @@ export interface ServerToClientEvents { connect: () => void // Game events - "game:status": (data: { name: Status; data: StatusDataMap[Status] }) => void - "game:successRoom": (data: string) => void - "game:successJoin": (gameId: string) => void - "game:totalPlayers": (count: number) => void - "game:errorMessage": (message: string) => void + "game:status": (_data: { name: Status; data: StatusDataMap[Status] }) => void + "game:successRoom": (_data: string) => void + "game:successJoin": (_gameId: string) => void + "game:totalPlayers": (_count: number) => void + "game:errorMessage": (_message: string) => void "game:startCooldown": () => void - "game:cooldown": (count: number) => void + "game:cooldown": (_count: number) => void "game:kick": () => void "game:reset": () => void - "game:updateQuestion": (data: { current: number; total: number }) => void - "game:playerAnswer": (count: number) => void + "game:updateQuestion": (_data: { current: number; total: number }) => void + "game:playerAnswer": (_count: number) => void // Player events - "player:successReconnect": (data: { + "player:successReconnect": (_data: { gameId: string status: { name: Status; data: StatusDataMap[Status] } player: { username: string; points: number } currentQuestion: GameUpdateQuestion }) => void - "player:updateLeaderboard": (data: { leaderboard: Player[] }) => void + "player:updateLeaderboard": (_data: { leaderboard: Player[] }) => void // Manager events - "manager:successReconnect": (data: { + "manager:successReconnect": (_data: { gameId: string status: { name: Status; data: StatusDataMap[Status] } players: Player[] currentQuestion: GameUpdateQuestion }) => void - "manager:quizzList": (quizzList: QuizzWithId[]) => void - "manager:gameCreated": (data: { gameId: string; inviteCode: string }) => void - "manager:statusUpdate": (data: { + "manager:quizzList": (_quizzList: QuizzWithId[]) => void + "manager:gameCreated": (_data: { gameId: string; inviteCode: string }) => void + "manager:statusUpdate": (_data: { status: Status data: StatusDataMap[Status] }) => void - "manager:newPlayer": (player: Player) => void - "manager:removePlayer": (playerId: string) => void - "manager:errorMessage": (message: string) => void - "manager:playerKicked": (playerId: string) => void + "manager:newPlayer": (_player: Player) => void + "manager:removePlayer": (_playerId: string) => void + "manager:errorMessage": (_message: string) => void + "manager:playerKicked": (_playerId: string) => void } export interface ClientToServerEvents { // Manager actions - "game:create": (quizzId: string) => void - "manager:auth": (password: string) => void - "manager:reconnect": (message: { gameId: string }) => void + "game:create": (_quizzId: string) => void + "manager:auth": (_password: string) => void + "manager:reconnect": (_message: { gameId: string }) => void "manager:kickPlayer": ( - message: MessageWithoutStatus<{ playerId: string }> + _message: MessageWithoutStatus<{ playerId: string }> ) => void - "manager:startGame": (message: MessageGameId) => void - "manager:abortQuiz": (message: MessageGameId) => void - "manager:nextQuestion": (message: MessageGameId) => void - "manager:showLeaderboard": (message: MessageGameId) => void + "manager:startGame": (_message: MessageGameId) => void + "manager:abortQuiz": (_message: MessageGameId) => void + "manager:nextQuestion": (_message: MessageGameId) => void + "manager:showLeaderboard": (_message: MessageGameId) => void // Player actions - "player:join": (inviteCode: string) => void - "player:login": (message: MessageWithoutStatus<{ username: string }>) => void - "player:reconnect": (message: { gameId: string }) => void + "player:join": (_inviteCode: string) => void + "player:login": (_message: MessageWithoutStatus<{ username: string }>) => void + "player:reconnect": (_message: { gameId: string }) => void "player:selectedAnswer": ( - message: MessageWithoutStatus<{ answerKey: number }> + _message: MessageWithoutStatus<{ answerKey: number }> ) => void // Common diff --git a/packages/common/src/types/game/status.ts b/packages/common/src/types/game/status.ts index dfcc5b2..3a73868 100644 --- a/packages/common/src/types/game/status.ts +++ b/packages/common/src/types/game/status.ts @@ -1,18 +1,19 @@ -import { Player } from "."; +import { Player } from "." -export enum Status { - SHOW_ROOM = "SHOW_ROOM", - SHOW_START = "SHOW_START", - SHOW_PREPARED = "SHOW_PREPARED", - SHOW_QUESTION = "SHOW_QUESTION", - SELECT_ANSWER = "SELECT_ANSWER", - SHOW_RESULT = "SHOW_RESULT", - SHOW_RESPONSES = "SHOW_RESPONSES", - SHOW_LEADERBOARD = "SHOW_LEADERBOARD", - FINISHED = "FINISHED", - WAIT = "WAIT", -} +export const STATUS = { + SHOW_ROOM: "SHOW_ROOM", + SHOW_START: "SHOW_START", + SHOW_PREPARED: "SHOW_PREPARED", + SHOW_QUESTION: "SHOW_QUESTION", + SELECT_ANSWER: "SELECT_ANSWER", + SHOW_RESULT: "SHOW_RESULT", + SHOW_RESPONSES: "SHOW_RESPONSES", + SHOW_LEADERBOARD: "SHOW_LEADERBOARD", + FINISHED: "FINISHED", + WAIT: "WAIT", +} as const +export type Status = (typeof STATUS)[keyof typeof STATUS] export type CommonStatusDataMap = { SHOW_START: { time: number; subject: string } @@ -49,10 +50,6 @@ type ManagerExtraStatus = { SHOW_LEADERBOARD: { leaderboard: Player[] } } -type PlayerExtraStatus = { - WAIT: { text: string } -} - -export type PlayerStatusDataMap = CommonStatusDataMap & PlayerExtraStatus +export type PlayerStatusDataMap = CommonStatusDataMap export type ManagerStatusDataMap = CommonStatusDataMap & ManagerExtraStatus export type StatusDataMap = PlayerStatusDataMap & ManagerStatusDataMap diff --git a/packages/socket/src/utils/validator.ts b/packages/common/src/validators/auth.ts similarity index 100% rename from packages/socket/src/utils/validator.ts rename to packages/common/src/validators/auth.ts diff --git a/packages/common/tsconfig.json b/packages/common/tsconfig.json index 3eb1a0e..42ed9cb 100644 --- a/packages/common/tsconfig.json +++ b/packages/common/tsconfig.json @@ -1,4 +1,5 @@ { + "extends": "../../tsconfig.json", "compilerOptions": { "target": "ESNext", "module": "ESNext", diff --git a/packages/config/game.json b/packages/config/game.json new file mode 100644 index 0000000..66f12d9 --- /dev/null +++ b/packages/config/game.json @@ -0,0 +1,4 @@ +{ + "managerPassword": "PASSWORD", + "music": true +} \ No newline at end of file diff --git a/packages/config/quizz/example.json b/packages/config/quizz/example.json new file mode 100644 index 0000000..c048d43 --- /dev/null +++ b/packages/config/quizz/example.json @@ -0,0 +1,41 @@ +{ + "subject": "Example Quizz", + "questions": [ + { + "question": "What is good answer ?", + "answers": [ + "No", + "Good answer", + "No", + "No" + ], + "solution": 1, + "cooldown": 5, + "time": 15 + }, + { + "question": "What is good answer with image ?", + "answers": [ + "No", + "No", + "No", + "Good answer" + ], + "image": "https://placehold.co/600x400.png", + "solution": 3, + "cooldown": 5, + "time": 20 + }, + { + "question": "What is good answer with two answers ?", + "answers": [ + "Good answer", + "No" + ], + "image": "https://placehold.co/600x400.png", + "solution": 0, + "cooldown": 5, + "time": 20 + } + ] +} \ No newline at end of file diff --git a/packages/socket/eslint.config.mjs b/packages/socket/eslint.config.mjs new file mode 100644 index 0000000..297a7d1 --- /dev/null +++ b/packages/socket/eslint.config.mjs @@ -0,0 +1,208 @@ +import js from "@eslint/js" +import { defineConfig } from "eslint/config" +import globals from "globals" +import tseslint from "typescript-eslint" + +export default defineConfig([ + { + ignores: ["**/node_modules/**", "**/dist/**"], + }, + { + files: ["**/*.ts"], + languageOptions: { + ...js.configs.recommended.languageOptions, + parser: tseslint.parser, + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + globals: { + ...globals.node, + }, + }, + plugins: { + "@typescript-eslint": tseslint.plugin, + }, + rules: { + ...js.configs.recommended.rules, + ...tseslint.configs.recommendedTypeChecked[0].rules, + + "array-callback-return": [ + "error", + { allowImplicit: false, checkForEach: true, allowVoid: true }, + ], + "no-await-in-loop": "error", + "no-constant-binary-expression": "error", + "no-constructor-return": "error", + "no-duplicate-imports": ["error", { includeExports: true }], + "no-new-native-nonconstructor": "error", + "no-promise-executor-return": ["error", { allowVoid: true }], + "no-self-compare": "error", + "no-template-curly-in-string": "error", + "no-unmodified-loop-condition": "error", + "no-unreachable-loop": "error", + "no-unused-private-class-members": "error", + "arrow-body-style": ["error", "as-needed"], + camelcase: [ + "error", + { + properties: "always", + ignoreDestructuring: true, + ignoreImports: true, + ignoreGlobals: true, + }, + ], + "capitalized-comments": [ + "error", + "always", + { ignoreConsecutiveComments: true }, + ], + "class-methods-use-this": ["error", { enforceForClassFields: true }], + complexity: ["warn", 40], + "consistent-return": "error", + curly: ["error", "all"], + "default-param-last": "error", + "dot-notation": "error", + eqeqeq: ["error", "always"], + "func-name-matching": "error", + "func-names": "error", + "func-style": ["error", "declaration", { allowArrowFunctions: true }], + "grouped-accessor-pairs": ["error", "getBeforeSet"], + "guard-for-in": "error", + "init-declarations": ["error", "always"], + "logical-assignment-operators": [ + "error", + "always", + { enforceForIfStatements: true }, + ], + "max-classes-per-file": ["error", { ignoreExpressions: true }], + "max-depth": ["error", 3], + "max-lines": [ + "error", + { max: 500, skipBlankLines: true, skipComments: true }, + ], + "max-nested-callbacks": ["error", 3], + "max-params": ["error", 4], + "multiline-comment-style": ["error", "separate-lines"], + "no-alert": "error", + "no-bitwise": "error", + "no-caller": "error", + "no-else-return": "error", + "no-empty-function": "error", + "no-empty-static-block": "error", + "no-eq-null": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-label": "error", + "no-implicit-coercion": "error", + "no-implicit-globals": "error", + "no-implied-eval": "error", + "no-inline-comments": "error", + "no-invalid-this": "error", + "no-iterator": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-lonely-if": "error", + "no-loop-func": "error", + "no-multi-assign": "error", + "no-multi-str": "error", + "no-nested-ternary": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-object-constructor": "error", + "no-octal-escape": "error", + "no-param-reassign": "error", + "no-plusplus": "error", + "no-proto": "error", + "no-return-assign": ["error", "always"], + "no-script-url": "error", + "no-sequences": "error", + "no-throw-literal": "error", + "no-undef-init": "error", + "no-unneeded-ternary": ["error", { defaultAssignment: false }], + "no-unused-expressions": ["error", { enforceForJSX: true }], + "no-unused-vars": ["error", { argsIgnorePattern: "^_" }], + "no-useless-call": "error", + "no-useless-computed-key": ["error", { enforceForClassMembers: true }], + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-var": "error", + "no-warning-comments": ["error", { terms: ["todo"] }], + "object-shorthand": ["error", "always"], + "one-var": ["error", "never"], + "operator-assignment": ["error", "always"], + "prefer-arrow-callback": "error", + "prefer-const": [ + "error", + { destructuring: "any", ignoreReadBeforeAssign: false }, + ], + "prefer-destructuring": "error", + "prefer-exponentiation-operator": "error", + "prefer-numeric-literals": "error", + "prefer-object-has-own": "error", + "prefer-object-spread": "error", + "prefer-promise-reject-errors": "error", + "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }], + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "error", + radix: "error", + "require-await": "error", + "require-unicode-regexp": "error", + "symbol-description": "error", + yoda: "error", + "line-comment-position": ["error", { position: "above" }], + indent: "off", + "newline-before-return": "error", + "no-undef": "error", + "padded-blocks": ["error", "never"], + "padding-line-between-statements": [ + "error", + { + blankLine: "always", + prev: "*", + next: [ + "break", + "case", + "cjs-export", + "class", + "continue", + "do", + "if", + "switch", + "try", + "while", + "return", + ], + }, + { + blankLine: "always", + prev: [ + "break", + "case", + "cjs-export", + "class", + "continue", + "do", + "if", + "switch", + "try", + "while", + "return", + ], + next: "*", + }, + ], + quotes: [ + "error", + "double", + { avoidEscape: true, allowTemplateLiterals: true }, + ], + "space-before-blocks": "error", + semi: ["error", "never"], + }, + }, +]) diff --git a/packages/socket/package.json b/packages/socket/package.json index f9b4205..8edcf74 100644 --- a/packages/socket/package.json +++ b/packages/socket/package.json @@ -5,7 +5,8 @@ "scripts": { "dev": "tsx watch src/index.ts", "build": "node esbuild.config.js", - "start": "node dist/index.cjs" + "start": "node dist/index.cjs", + "lint": "eslint" }, "keywords": [], "author": "", @@ -13,12 +14,18 @@ "dependencies": { "@rahoot/common": "workspace:*", "@t3-oss/env-core": "^0.13.8", + "dayjs": "^1.11.18", "socket.io": "^4.8.1", "uuid": "^13.0.0", "zod": "^4.1.11" }, "devDependencies": { + "@eslint/js": "^9.38.0", + "@types/node": "^24.8.1", "esbuild": "^0.25.10", - "tsx": "^4.20.6" + "eslint": "^9", + "globals": "^16.4.0", + "tsx": "^4.20.6", + "typescript-eslint": "^8.46.1" } } diff --git a/packages/socket/src/index.ts b/packages/socket/src/index.ts index d784de6..646831e 100644 --- a/packages/socket/src/index.ts +++ b/packages/socket/src/index.ts @@ -1,30 +1,28 @@ import { Server } from "@rahoot/common/types/game/socket" +import { inviteCodeValidator } from "@rahoot/common/validators/auth" import env from "@rahoot/socket/env" import Config from "@rahoot/socket/services/config" import Game from "@rahoot/socket/services/game" -import { - findManagerGameByClientId, - findPlayerGameByClientId, - withGame, -} from "@rahoot/socket/utils/game" -import { inviteCodeValidator } from "@rahoot/socket/utils/validator" +import Registry from "@rahoot/socket/services/registry" +import { withGame } from "@rahoot/socket/utils/game" import { Server as ServerIO } from "socket.io" const io: Server = new ServerIO() Config.init() -let games: Game[] = [] +const registry = Registry.getInstance() const port = env.SOCKER_PORT || 3001 console.log(`Socket server running on port ${port}`) io.listen(Number(port)) io.on("connection", (socket) => { - console.log(`A user connected ${socket.id}`) - console.log(socket.handshake.auth) + console.log( + `A user connected: socketId: ${socket.id}, clientId: ${socket.handshake.auth.clientId}` + ) socket.on("player:reconnect", () => { - const game = findPlayerGameByClientId(socket.handshake.auth.clientId, games) + const game = registry.getPlayerGame(socket.handshake.auth.clientId) if (game) { game.reconnect(socket) @@ -36,13 +34,11 @@ io.on("connection", (socket) => { }) socket.on("manager:reconnect", () => { - const game = findManagerGameByClientId( - socket.handshake.auth.clientId, - games - ) + const game = registry.getManagerGame(socket.handshake.auth.clientId) if (game) { game.reconnect(socket) + registry.reactivateGame(game.gameId) return } @@ -56,6 +52,7 @@ io.on("connection", (socket) => { if (password !== config.managerPassword) { socket.emit("manager:errorMessage", "Invalid password") + return } @@ -72,23 +69,24 @@ io.on("connection", (socket) => { if (!quizz) { socket.emit("game:errorMessage", "Quizz not found") + return } const game = new Game(io, socket, quizz) - - games.push(game) + registry.addGame(game) }) - socket.on("player:join", async (inviteCode) => { + socket.on("player:join", (inviteCode) => { const result = inviteCodeValidator.safeParse(inviteCode) if (result.error) { socket.emit("game:errorMessage", result.error.issues[0].message) + return } - const game = games.find((g) => g.inviteCode === inviteCode) + const game = registry.getGameByInviteCode(inviteCode) if (!game) { socket.emit("game:errorMessage", "Game not found") @@ -100,53 +98,54 @@ io.on("connection", (socket) => { }) socket.on("player:login", ({ gameId, data }) => - withGame(gameId, socket, games, (game) => game.join(socket, data.username)) + withGame(gameId, socket, (game) => game.join(socket, data.username)) ) socket.on("manager:kickPlayer", ({ gameId, data }) => - withGame(gameId, socket, games, (game) => - game.kickPlayer(socket, data.playerId) - ) + withGame(gameId, socket, (game) => game.kickPlayer(socket, data.playerId)) ) socket.on("manager:startGame", ({ gameId }) => - withGame(gameId, socket, games, (game) => game.start(socket)) + withGame(gameId, socket, (game) => game.start(socket)) ) socket.on("player:selectedAnswer", ({ gameId, data }) => - withGame(gameId, socket, games, (game) => + withGame(gameId, socket, (game) => game.selectAnswer(socket, data.answerKey) ) ) socket.on("manager:abortQuiz", ({ gameId }) => - withGame(gameId, socket, games, (game) => game.abortRound(socket)) + withGame(gameId, socket, (game) => game.abortRound(socket)) ) socket.on("manager:nextQuestion", ({ gameId }) => - withGame(gameId, socket, games, (game) => game.nextRound(socket)) + withGame(gameId, socket, (game) => game.nextRound(socket)) ) socket.on("manager:showLeaderboard", ({ gameId }) => - withGame(gameId, socket, games, (game) => game.showLeaderboard()) + withGame(gameId, socket, (game) => game.showLeaderboard()) ) socket.on("disconnect", () => { console.log(`user disconnected ${socket.id}`) - const managerGame = games.find((g) => g.manager.id === socket.id) - if (managerGame && !managerGame.started) { - console.log("Reset game (manager disconnected)") + const managerGame = registry.getGameByManagerSocketId(socket.id) - managerGame.abortCooldown() - io.to(managerGame.gameId).emit("game:reset") + if (managerGame) { + registry.markGameAsEmpty(managerGame) - games = games.filter((g) => g.gameId !== managerGame.gameId) + if (!managerGame.started) { + console.log("Reset game (manager disconnected)") + managerGame.abortCooldown() + io.to(managerGame.gameId).emit("game:reset") + registry.removeGame(managerGame.gameId) - return + return + } } - const game = games.find((g) => g.players.some((p) => p.id === socket.id)) + const game = registry.getGameByPlayerSocketId(socket.id) if (!game || game.started) { return @@ -166,3 +165,13 @@ io.on("connection", (socket) => { console.log(`Removed player ${player.username} from game ${game.gameId}`) }) }) + +process.on("SIGINT", () => { + Registry.getInstance().cleanup() + process.exit(0) +}) + +process.on("SIGTERM", () => { + Registry.getInstance().cleanup() + process.exit(0) +}) diff --git a/packages/socket/src/services/config.ts b/packages/socket/src/services/config.ts index 9c1bd50..e052542 100644 --- a/packages/socket/src/services/config.ts +++ b/packages/socket/src/services/config.ts @@ -2,11 +2,19 @@ import { QuizzWithId } from "@rahoot/common/types/game" import fs from "fs" import { resolve } from "path" -const getPath = (path: string) => resolve(process.cwd(), "../../config", path) +const getPath = (path: string = "") => + resolve(process.cwd(), "../../config", path) class Config { static init() { + const isConfigFolderExists = fs.existsSync(getPath()) + + if (!isConfigFolderExists) { + fs.mkdirSync(getPath()) + } + const isGameConfigExists = fs.existsSync(getPath("game.json")) + if (!isGameConfigExists) { fs.writeFileSync( getPath("game.json"), @@ -22,6 +30,7 @@ class Config { } const isQuizzExists = fs.existsSync(getPath("quizz")) + if (!isQuizzExists) { fs.mkdirSync(getPath("quizz")) @@ -65,20 +74,25 @@ class Config { static game() { const isExists = fs.existsSync(getPath("game.json")) + if (!isExists) { throw new Error("Game config not found") } try { const config = fs.readFileSync(getPath("game.json"), "utf-8") + return JSON.parse(config) } catch (error) { console.error("Failed to read game config:", error) } + + return {} } static quizz() { const isExists = fs.existsSync(getPath("quizz")) + if (!isExists) { return [] } @@ -99,9 +113,11 @@ class Config { ...config, } }) + return quizz || [] } catch (error) { console.error("Failed to read quizz config:", error) + return [] } } diff --git a/packages/socket/src/services/game.ts b/packages/socket/src/services/game.ts index 3e24428..cb8d3d5 100644 --- a/packages/socket/src/services/game.ts +++ b/packages/socket/src/services/game.ts @@ -1,6 +1,6 @@ import { Answer, Player, Quizz } from "@rahoot/common/types/game" import { Server, Socket } from "@rahoot/common/types/game/socket" -import { Status, StatusDataMap } from "@rahoot/common/types/game/status" +import { Status, STATUS, StatusDataMap } from "@rahoot/common/types/game/status" import { createInviteCode, timeToPoint } from "@rahoot/socket/utils/game" import sleep from "@rahoot/socket/utils/sleep" import { v4 as uuid } from "uuid" @@ -114,7 +114,7 @@ class Game { const playerData = { id: socket.id, clientId: socket.handshake.auth.clientId, - username: username, + username, points: 0, } @@ -148,7 +148,7 @@ class Game { } reconnect(socket: Socket) { - const clientId = socket.handshake.auth.clientId + const { clientId } = socket.handshake.auth const isManager = this.manager.clientId === clientId if (!isManager) { @@ -175,7 +175,7 @@ class Game { const status = this.managerStatus || this.lastBroadcastStatus || { - name: Status.WAIT, + name: STATUS.WAIT, data: { text: "Waiting for players" }, } @@ -188,7 +188,7 @@ class Game { console.log(`Manager reconnected to game ${this.inviteCode}`) - return + return true } const player = this.players.find((p) => p.clientId === clientId)! @@ -197,7 +197,7 @@ class Game { const status = this.playerStatus.get(oldSocketId) || this.lastBroadcastStatus || { - name: Status.WAIT, + name: STATUS.WAIT, data: { text: "Waiting for players" }, } @@ -223,9 +223,9 @@ class Game { return true } - async startCooldown(seconds: number) { + startCooldown(seconds: number): Promise { if (this.cooldown.active) { - return + return Promise.resolve() } this.cooldown.active = true @@ -237,6 +237,7 @@ class Game { this.cooldown.active = false clearInterval(cooldownTimeout) resolve() + return } @@ -246,10 +247,8 @@ class Game { }) } - async abortCooldown() { - if (this.cooldown.active) { - this.cooldown.active = false - } + abortCooldown() { + this.cooldown.active &&= false } async start(socket: Socket) { @@ -263,7 +262,7 @@ class Game { this.started = true - this.broadcastStatus(Status.SHOW_START, { + this.broadcastStatus(STATUS.SHOW_START, { time: 3, subject: this.quizz.subject, }) @@ -290,7 +289,7 @@ class Game { total: this.quizz.questions.length, }) - this.broadcastStatus(Status.SHOW_PREPARED, { + this.broadcastStatus(STATUS.SHOW_PREPARED, { totalAnswers: question.answers.length, questionNumber: this.round.currentQuestion + 1, }) @@ -301,7 +300,7 @@ class Game { return } - this.broadcastStatus(Status.SHOW_QUESTION, { + this.broadcastStatus(STATUS.SHOW_QUESTION, { question: question.question, image: question.image, cooldown: question.cooldown, @@ -315,7 +314,7 @@ class Game { this.round.startTime = Date.now() - this.broadcastStatus(Status.SELECT_ANSWER, { + this.broadcastStatus(STATUS.SELECT_ANSWER, { question: question.question, answers: question.answers, image: question.image, @@ -332,10 +331,11 @@ class Game { await this.showResults(question) } - async showResults(question: any) { + showResults(question: any) { const totalType = this.round.playersAnswers.reduce( (acc: Record, { answerId }) => { acc[answerId] = (acc[answerId] || 0) + 1 + return acc }, {} @@ -366,7 +366,7 @@ class Game { const rank = index + 1 const aheadPlayer = sortedPlayers[index - 1] - this.sendStatus(player.id, Status.SHOW_RESULT, { + this.sendStatus(player.id, STATUS.SHOW_RESULT, { correct: player.lastCorrect, message: player.lastCorrect ? "Nice!" : "Too bad", points: player.lastPoints, @@ -376,7 +376,7 @@ class Game { }) }) - this.sendStatus(this.manager.id, Status.SHOW_RESPONSES, { + this.sendStatus(this.manager.id, STATUS.SHOW_RESPONSES, { question: question.question, responses: totalType, correct: question.solution, @@ -387,7 +387,7 @@ class Game { this.round.playersAnswers = [] } - async selectAnswer(socket: Socket, answerId: number) { + selectAnswer(socket: Socket, answerId: number) { const player = this.players.find((player) => player.id === socket.id) const question = this.quizz.questions[this.round.currentQuestion] @@ -405,7 +405,7 @@ class Game { points: timeToPoint(this.round.startTime, question.time), }) - this.sendStatus(socket.id, Status.WAIT, { + this.sendStatus(socket.id, STATUS.WAIT, { text: "Waiting for the players to answer", }) @@ -458,7 +458,7 @@ class Game { if (isLastRound) { this.started = false - this.broadcastStatus(Status.FINISHED, { + this.broadcastStatus(STATUS.FINISHED, { subject: this.quizz.subject, top: sortedPlayers.slice(0, 3), }) @@ -466,7 +466,7 @@ class Game { return } - this.sendStatus(this.manager.id, Status.SHOW_LEADERBOARD, { + this.sendStatus(this.manager.id, STATUS.SHOW_LEADERBOARD, { leaderboard: sortedPlayers.slice(0, 5), }) } diff --git a/packages/socket/src/services/registry.ts b/packages/socket/src/services/registry.ts new file mode 100644 index 0000000..efe0fd5 --- /dev/null +++ b/packages/socket/src/services/registry.ts @@ -0,0 +1,158 @@ +import Game from "@rahoot/socket/services/game" +import dayjs from "dayjs" + +interface EmptyGame { + since: number + game: Game +} + +class Registry { + private static instance: Registry | null = null + private games: Game[] = [] + private emptyGames: EmptyGame[] = [] + private cleanupInterval: ReturnType | null = null + private readonly EMPTY_GAME_TIMEOUT_MINUTES = 5 + private readonly CLEANUP_INTERVAL_MS = 60_000 + + private constructor() { + this.startCleanupTask() + } + + static getInstance(): Registry { + Registry.instance ||= new Registry() + + return Registry.instance + } + + addGame(game: Game): void { + this.games.push(game) + console.log(`Game ${game.gameId} added. Total games: ${this.games.length}`) + } + + getGameById(gameId: string): Game | undefined { + return this.games.find((g) => g.gameId === gameId) + } + + getGameByInviteCode(inviteCode: string): Game | undefined { + return this.games.find((g) => g.inviteCode === inviteCode) + } + + getPlayerGame(clientId: string): Game | undefined { + return this.games.find((g) => + g.players.some((p) => p.clientId === clientId) + ) + } + + getManagerGame(clientId: string): Game | undefined { + return this.games.find((g) => g.manager.clientId === clientId) + } + + getGameByManagerSocketId(socketId: string): Game | undefined { + return this.games.find((g) => g.manager.id === socketId) + } + + getGameByPlayerSocketId(socketId: string): Game | undefined { + return this.games.find((g) => g.players.some((p) => p.id === socketId)) + } + + markGameAsEmpty(game: Game): void { + const alreadyEmpty = this.emptyGames.find( + (g) => g.game.gameId === game.gameId + ) + + if (!alreadyEmpty) { + this.emptyGames.push({ + since: dayjs().unix(), + game, + }) + console.log( + `Game ${game.gameId} marked as empty. Total empty games: ${this.emptyGames.length}` + ) + } + } + + reactivateGame(gameId: string): void { + const initialLength = this.emptyGames.length + this.emptyGames = this.emptyGames.filter((g) => g.game.gameId !== gameId) + + if (this.emptyGames.length < initialLength) { + console.log( + `Game ${gameId} reactivated. Remaining empty games: ${this.emptyGames.length}` + ) + } + } + + removeGame(gameId: string): boolean { + const initialLength = this.games.length + this.games = this.games.filter((g) => g.gameId !== gameId) + this.emptyGames = this.emptyGames.filter((g) => g.game.gameId !== gameId) + + const removed = this.games.length < initialLength + + if (removed) { + console.log(`Game ${gameId} removed. Total games: ${this.games.length}`) + } + + return removed + } + + getAllGames(): Game[] { + return [...this.games] + } + + getGameCount(): number { + return this.games.length + } + + getEmptyGameCount(): number { + return this.emptyGames.length + } + + private cleanupEmptyGames(): void { + const now = dayjs() + const stillEmpty = this.emptyGames.filter( + (g) => + now.diff(dayjs.unix(g.since), "minute") < + this.EMPTY_GAME_TIMEOUT_MINUTES + ) + + if (stillEmpty.length === this.emptyGames.length) { + return + } + + const removed = this.emptyGames.filter((g) => !stillEmpty.includes(g)) + const removedGameIds = removed.map((r) => r.game.gameId) + + this.games = this.games.filter((g) => !removedGameIds.includes(g.gameId)) + this.emptyGames = stillEmpty + + console.log( + `Removed ${removed.length} empty game(s). Remaining games: ${this.games.length}` + ) + } + + private startCleanupTask(): void { + this.cleanupInterval = setInterval(() => { + this.cleanupEmptyGames() + }, this.CLEANUP_INTERVAL_MS) + + console.log("Game cleanup task started") + } + + stopCleanupTask(): void { + if (this.cleanupInterval) { + clearInterval(this.cleanupInterval) + this.cleanupInterval = null + console.log("Game cleanup task stopped") + } + } + + cleanup(): void { + this.stopCleanupTask() + this.games = [] + this.emptyGames = [] + console.log("Registry cleaned up") + } +} + +export default Registry diff --git a/packages/socket/src/utils/game.ts b/packages/socket/src/utils/game.ts index 9a7f92a..f6923d6 100644 --- a/packages/socket/src/utils/game.ts +++ b/packages/socket/src/utils/game.ts @@ -1,29 +1,28 @@ import { Socket } from "@rahoot/common/types/game/socket" import Game from "@rahoot/socket/services/game" +import Registry from "@rahoot/socket/services/registry" -export const withGame = ( +export const withGame = ( gameId: string | undefined, socket: Socket, - games: Game[], - handler: (game: Game) => T -): T | void => { - let game = null - - if (gameId) { - game = games.find((g) => g.gameId === gameId) - } else { - game = games.find( - (g) => - g.players.find((p) => p.id === socket.id) || g.manager.id === socket.id - ) - } - - if (!game) { + callback: (_game: Game) => void +): void => { + if (!gameId) { socket.emit("game:errorMessage", "Game not found") + return } - return handler(game) + const registry = Registry.getInstance() + const game = registry.getGameById(gameId) + + if (!game) { + socket.emit("game:errorMessage", "Game not found") + + return + } + + callback(game) } export const createInviteCode = (length = 6) => { @@ -50,25 +49,3 @@ export const timeToPoint = (startTime: number, secondes: number): number => { return points } - -export const findPlayerGameByClientId = (clientId: string, games: Game[]) => { - const playerGame = games.find((g) => - g.players.find((p) => p.clientId === clientId) - ) - - if (playerGame) { - return playerGame - } - - return null -} - -export const findManagerGameByClientId = (clientId: string, games: Game[]) => { - const managerGame = games.find((g) => g.manager.clientId === clientId) - - if (managerGame) { - return managerGame - } - - return null -} diff --git a/packages/socket/tsconfig.json b/packages/socket/tsconfig.json index 42ed9cb..43390f3 100644 --- a/packages/socket/tsconfig.json +++ b/packages/socket/tsconfig.json @@ -3,6 +3,7 @@ "compilerOptions": { "target": "ESNext", "module": "ESNext", + "types": ["node"], "moduleResolution": "bundler", "strict": true, "skipLibCheck": true, diff --git a/packages/web/eslint.config.mjs b/packages/web/eslint.config.mjs index 8df583a..6b41f73 100644 --- a/packages/web/eslint.config.mjs +++ b/packages/web/eslint.config.mjs @@ -1,22 +1,23 @@ +import js from "@eslint/js" import nextPlugin from "@next/eslint-plugin-next" -import tsEslintPlugin from "@typescript-eslint/eslint-plugin" -import tsEslintParser from "@typescript-eslint/parser" import reactPlugin from "eslint-plugin-react" import reactHooksPlugin from "eslint-plugin-react-hooks" import { defineConfig } from "eslint/config" import globals from "globals" +import tseslint from "typescript-eslint" export default defineConfig([ { ignores: ["**/node_modules/**", "**/.next/**"], }, { - files: ["**/*.ts", "**/*.tsx"], + files: ["**/*.{ts,tsx}"], languageOptions: { - ecmaVersion: "latest", - sourceType: "module", - parser: tsEslintParser, + ...js.configs.recommended.languageOptions, + parser: tseslint.parser, parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, ecmaFeatures: { jsx: true }, }, globals: { @@ -25,7 +26,7 @@ export default defineConfig([ }, }, plugins: { - "@typescript-eslint": tsEslintPlugin, + "@typescript-eslint": tseslint.plugin, react: reactPlugin, "react-hooks": reactHooksPlugin, "@next/next": nextPlugin, @@ -36,6 +37,10 @@ export default defineConfig([ }, }, rules: { + ...js.configs.recommended.rules, + ...tseslint.configs.recommendedTypeChecked[0].rules, + ...reactPlugin.configs.recommended.rules, + "array-callback-return": [ "error", { allowImplicit: false, checkForEach: true, allowVoid: true }, @@ -213,7 +218,7 @@ export default defineConfig([ "space-before-blocks": "error", semi: ["error", "never"], - // Extra rules + // React + Hooks + Next.js "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "off", "react/no-unescaped-entities": ["error", { forbid: [">", "}"] }], diff --git a/packages/web/package.json b/packages/web/package.json index 7fa8e4c..7d547d7 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -12,7 +12,7 @@ "@rahoot/socket": "workspace:*", "@t3-oss/env-nextjs": "^0.13.8", "clsx": "^2.1.1", - "ky": "^1.11.0", + "ky": "^1.12.0", "next": "15.5.4", "react": "19.1.0", "react-confetti": "^6.4.0", @@ -26,21 +26,20 @@ "zustand": "^5.0.8" }, "devDependencies": { - "@eslint/eslintrc": "^3", - "@tailwindcss/postcss": "^4", - "@types/node": "^20", - "@types/react": "^19", - "@types/react-dom": "^19", - "@typescript-eslint/eslint-plugin": "^8.45.0", - "@typescript-eslint/parser": "^8.45.0", - "eslint": "^9", + "@eslint/eslintrc": "^3.3.1", + "@tailwindcss/postcss": "^4.1.14", + "@types/node": "^20.19.22", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", + "eslint": "^9.38.0", "eslint-config-next": "15.5.4", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^6.1.1", "globals": "^16.4.0", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.6.14", - "tailwindcss": "^4", - "typescript": "^5" + "tailwindcss": "^4.1.14", + "typescript": "^5.9.3", + "typescript-eslint": "^8.46.1" } } diff --git a/packages/web/src/app/(auth)/layout.tsx b/packages/web/src/app/(auth)/layout.tsx index 379d167..cda8be6 100644 --- a/packages/web/src/app/(auth)/layout.tsx +++ b/packages/web/src/app/(auth)/layout.tsx @@ -1,6 +1,9 @@ "use client" +import logo from "@rahoot/web/assets/logo.svg" +import Loader from "@rahoot/web/components/Loader" import { useSocket } from "@rahoot/web/contexts/socketProvider" +import Image from "next/image" import { PropsWithChildren, useEffect } from "react" const AuthLayout = ({ children }: PropsWithChildren) => { @@ -11,7 +14,34 @@ const AuthLayout = ({ children }: PropsWithChildren) => { } }, [connect, isConnected]) - return children + if (!isConnected) { + return ( +
+
+
+
+
+ + logo + +

+ Loading... +

+
+ ) + } + + return ( +
+
+
+
+
+ + logo + {children} +
+ ) } export default AuthLayout diff --git a/packages/web/src/app/(auth)/manager/page.tsx b/packages/web/src/app/(auth)/manager/page.tsx index 63b63a0..b7c3b05 100644 --- a/packages/web/src/app/(auth)/manager/page.tsx +++ b/packages/web/src/app/(auth)/manager/page.tsx @@ -31,7 +31,6 @@ export default function Manager() { socket?.emit("manager:auth", password) } const handleCreate = (quizzId: string) => { - console.log(quizzId) socket?.emit("game:create", quizzId) } diff --git a/packages/web/src/app/(auth)/page.tsx b/packages/web/src/app/(auth)/page.tsx index b4dff88..546b3b8 100644 --- a/packages/web/src/app/(auth)/page.tsx +++ b/packages/web/src/app/(auth)/page.tsx @@ -1,11 +1,9 @@ "use client" -import logo from "@rahoot/web/assets/logo.svg" import Room from "@rahoot/web/components/game/join/Room" import Username from "@rahoot/web/components/game/join/Username" import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" import { usePlayerStore } from "@rahoot/web/stores/player" -import Image from "next/image" import { useEffect } from "react" import toast from "react-hot-toast" @@ -23,16 +21,9 @@ export default function Home() { toast.error(message) }) - return ( -
-
-
-
-
+ if (player) { + return + } - logo - - {!player ? : } -
- ) + return } diff --git a/packages/web/src/app/game/[gameId]/page.tsx b/packages/web/src/app/game/[gameId]/page.tsx index 6bcd0b9..1ab789a 100644 --- a/packages/web/src/app/game/[gameId]/page.tsx +++ b/packages/web/src/app/game/[gameId]/page.tsx @@ -1,6 +1,6 @@ "use client" -import { Status } from "@rahoot/common/types/game/status" +import { STATUS } from "@rahoot/common/types/game/status" import GameWrapper from "@rahoot/web/components/game/GameWrapper" import Answers from "@rahoot/web/components/game/states/Answers" import Prepared from "@rahoot/web/components/game/states/Prepared" @@ -17,10 +17,9 @@ import toast from "react-hot-toast" export default function Game() { const router = useRouter() - const { socket, isConnected } = useSocket() + const { socket } = useSocket() const { gameId: gameIdParam }: { gameId?: string } = useParams() - const { status, setPlayer, logout, setGameId, setStatus, resetStatus } = - usePlayerStore() + const { status, setPlayer, setGameId, setStatus, reset } = usePlayerStore() const { setQuestionStates } = useQuestionStore() useEvent("connect", () => { @@ -45,16 +44,16 @@ export default function Game() { } }) - useEvent("game:reset", () => { + useEvent("game:kick", () => { router.replace("/") - resetStatus() - logout() - toast("The game has been reset by the host") + reset() }) - if (!isConnected) { - return null - } + useEvent("game:reset", () => { + router.replace("/") + reset() + toast("The game has been reset by the host") + }) if (!gameIdParam) { return null @@ -63,36 +62,36 @@ export default function Game() { let component = null switch (status.name) { - case Status.WAIT: + case STATUS.WAIT: component = break - case Status.SHOW_START: + case STATUS.SHOW_START: component = break - case Status.SHOW_PREPARED: + case STATUS.SHOW_PREPARED: component = break - case Status.SHOW_QUESTION: + case STATUS.SHOW_QUESTION: component = break - case Status.SHOW_RESULT: + case STATUS.SHOW_RESULT: component = break - case Status.SELECT_ANSWER: + case STATUS.SELECT_ANSWER: component = break } - return {component} + return {component} } diff --git a/packages/web/src/app/game/manager/[gameId]/page.tsx b/packages/web/src/app/game/manager/[gameId]/page.tsx index 67cf094..b00d291 100644 --- a/packages/web/src/app/game/manager/[gameId]/page.tsx +++ b/packages/web/src/app/game/manager/[gameId]/page.tsx @@ -1,6 +1,6 @@ "use client" -import { Status } from "@rahoot/common/types/game/status" +import { STATUS } from "@rahoot/common/types/game/status" import GameWrapper from "@rahoot/web/components/game/GameWrapper" import Answers from "@rahoot/web/components/game/states/Answers" import Leaderboard from "@rahoot/web/components/game/states/Leaderboard" @@ -15,15 +15,14 @@ import { useManagerStore } from "@rahoot/web/stores/manager" import { useQuestionStore } from "@rahoot/web/stores/question" import { GAME_STATE_COMPONENTS_MANAGER } from "@rahoot/web/utils/constants" import { useParams, useRouter } from "next/navigation" -import { useEffect, useState } from "react" import toast from "react-hot-toast" export default function ManagerGame() { const router = useRouter() const { gameId: gameIdParam }: { gameId?: string } = useParams() - const { socket, isConnected } = useSocket() - const [nextText, setNextText] = useState("Start") - const { gameId, status, setGameId, setStatus, setPlayers } = useManagerStore() + const { socket } = useSocket() + const { gameId, status, setGameId, setStatus, setPlayers, reset } = + useManagerStore() const { setQuestionStates } = useQuestionStore() useEvent("game:status", ({ name, data }) => { @@ -41,6 +40,7 @@ export default function ManagerGame() { useEvent( "manager:successReconnect", ({ gameId, status, players, currentQuestion }) => { + console.log("manager:successReconnect", gameId) setGameId(gameId) setStatus(status.name, status.data) setPlayers(players) @@ -50,43 +50,32 @@ export default function ManagerGame() { useEvent("game:reset", () => { router.replace("/manager") + reset() toast("Game is not available anymore") }) - useEffect(() => { - if (status.name === Status.SHOW_START) { - setNextText("Start") - } - }, [status.name]) - - if (!isConnected) { - return null - } - - if (!gameId) { - return null - } - const handleSkip = () => { - setNextText("Skip") + if (!gameId) { + return + } switch (status.name) { - case Status.SHOW_ROOM: + case STATUS.SHOW_ROOM: socket?.emit("manager:startGame", { gameId }) break - case Status.SELECT_ANSWER: + case STATUS.SELECT_ANSWER: socket?.emit("manager:abortQuiz", { gameId }) break - case Status.SHOW_RESPONSES: + case STATUS.SHOW_RESPONSES: socket?.emit("manager:showLeaderboard", { gameId }) break - case Status.SHOW_LEADERBOARD: + case STATUS.SHOW_LEADERBOARD: socket?.emit("manager:nextQuestion", { gameId }) break @@ -96,49 +85,49 @@ export default function ManagerGame() { let component = null switch (status.name) { - case Status.SHOW_ROOM: + case STATUS.SHOW_ROOM: component = break - case Status.SHOW_START: + case STATUS.SHOW_START: component = break - case Status.SHOW_PREPARED: + case STATUS.SHOW_PREPARED: component = break - case Status.SHOW_QUESTION: + case STATUS.SHOW_QUESTION: component = break - case Status.SELECT_ANSWER: + case STATUS.SELECT_ANSWER: component = break - case Status.SHOW_RESPONSES: + case STATUS.SHOW_RESPONSES: component = break - case Status.SHOW_LEADERBOARD: + case STATUS.SHOW_LEADERBOARD: component = break - case Status.FINISHED: + case STATUS.FINISHED: component = break } return ( - + {component} ) diff --git a/packages/web/src/app/globals.css b/packages/web/src/app/globals.css index c7b2bcf..ede069a 100644 --- a/packages/web/src/app/globals.css +++ b/packages/web/src/app/globals.css @@ -5,6 +5,11 @@ --color-secondary: #1a140b; } +button:not(:disabled), +[role="button"]:not(:disabled) { + cursor: pointer; +} + .btn-shadow { box-shadow: rgba(0, 0, 0, 0.25) 0px -4px inset; } diff --git a/packages/web/src/components/Loader.tsx b/packages/web/src/components/Loader.tsx index 0a403c3..a760dec 100644 --- a/packages/web/src/components/Loader.tsx +++ b/packages/web/src/components/Loader.tsx @@ -1,6 +1,12 @@ import loader from "@rahoot/web/assets/loader.svg" import Image from "next/image" -export default function Loader() { - return loader +type Props = { + className?: string } + +const Loader = ({ className }: Props) => ( + loader +) + +export default Loader diff --git a/packages/web/src/components/game/GameWrapper.tsx b/packages/web/src/components/game/GameWrapper.tsx index 225b9ea..49eb8ed 100644 --- a/packages/web/src/components/game/GameWrapper.tsx +++ b/packages/web/src/components/game/GameWrapper.tsx @@ -1,41 +1,32 @@ "use client" +import { Status } from "@rahoot/common/types/game/status" import background from "@rahoot/web/assets/background.webp" import Button from "@rahoot/web/components/Button" import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" import { usePlayerStore } from "@rahoot/web/stores/player" import { useQuestionStore } from "@rahoot/web/stores/question" +import { MANAGER_SKIP_BTN } from "@rahoot/web/utils/constants" import Image from "next/image" -import { useRouter } from "next/navigation" -import { PropsWithChildren, useEffect } from "react" +import { PropsWithChildren } from "react" +import Loader from "../Loader" type Props = PropsWithChildren & { - textNext?: string + statusName: Status onNext?: () => void manager?: boolean } export default function GameWrapper({ children, - textNext, + statusName, onNext, manager, }: Props) { - const { isConnected, connect } = useSocket() - const { player, logout } = usePlayerStore() + const { isConnected } = useSocket() + const { player } = usePlayerStore() const { questionStates, setQuestionStates } = useQuestionStore() - const router = useRouter() - - useEffect(() => { - if (!isConnected) { - connect() - } - }, [connect, isConnected]) - - useEvent("game:kick", () => { - logout() - router.replace("/") - }) + const next = MANAGER_SKIP_BTN[statusName] || null useEvent("game:updateQuestion", ({ current, total }) => { setQuestionStates({ @@ -54,32 +45,41 @@ export default function GameWrapper({ />
-
- {questionStates && ( -
- {`${questionStates.current} / ${questionStates.total}`} -
- )} - - {manager && ( - - )} -
- - {children} - - {!manager && ( -
-

{player?.username}

-
- {player?.points} -
+ {!isConnected && !statusName ? ( +
+ +

Connecting...

+ ) : ( + <> +
+ {questionStates && ( +
+ {`${questionStates.current} / ${questionStates.total}`} +
+ )} + + {manager && next && ( + + )} +
+ + {children} + + {!manager && ( +
+

{player?.username}

+
+ {player?.points} +
+
+ )} + )} ) diff --git a/packages/web/src/components/game/create/ManagerPassword.tsx b/packages/web/src/components/game/create/ManagerPassword.tsx index 524f06a..653e8e5 100644 --- a/packages/web/src/components/game/create/ManagerPassword.tsx +++ b/packages/web/src/components/game/create/ManagerPassword.tsx @@ -1,15 +1,12 @@ -import logo from "@rahoot/web/assets/logo.svg" import Button from "@rahoot/web/components/Button" import Form from "@rahoot/web/components/Form" import Input from "@rahoot/web/components/Input" import { useEvent } from "@rahoot/web/contexts/socketProvider" -import Image from "next/image" import { KeyboardEvent, useState } from "react" import toast from "react-hot-toast" type Props = { - // eslint-disable-next-line no-unused-vars - onSubmit: (password: string) => void + onSubmit: (_password: string) => void } export default function ManagerPassword({ onSubmit }: Props) { @@ -30,23 +27,14 @@ export default function ManagerPassword({ onSubmit }: Props) { }) return ( -
-
-
-
-
- - logo - -
- setPassword(e.target.value)} - onKeyDown={handleKeyDown} - placeholder="Manager password" - /> - -
-
+
+ setPassword(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="Manager password" + /> + +
) } diff --git a/packages/web/src/components/game/create/SelectQuizz.tsx b/packages/web/src/components/game/create/SelectQuizz.tsx index d4b0d5b..2fc6b81 100644 --- a/packages/web/src/components/game/create/SelectQuizz.tsx +++ b/packages/web/src/components/game/create/SelectQuizz.tsx @@ -1,8 +1,6 @@ import { Quizz } from "@rahoot/common/types/game" -import logo from "@rahoot/web/assets/logo.svg" import Button from "@rahoot/web/components/Button" import clsx from "clsx" -import Image from "next/image" import { useState } from "react" import toast from "react-hot-toast" @@ -10,8 +8,7 @@ type QuizzWithId = Quizz & { id: string } type Props = { quizzList: QuizzWithId[] - // eslint-disable-next-line no-unused-vars - onSelect: (id: string) => void + onSelect: (_id: string) => void } export default function SelectQuizz({ quizzList, onSelect }: Props) { @@ -36,44 +33,32 @@ export default function SelectQuizz({ quizzList, onSelect }: Props) { } return ( -
-
-
-
-
+
+
+

Select a quizz

+
+ {quizzList.map((quizz) => ( + - ))} -
+ >
+ + ))}
-
- + + ) } diff --git a/packages/web/src/components/icons/Pentagon.tsx b/packages/web/src/components/icons/Pentagon.tsx index d734871..63e9cef 100644 --- a/packages/web/src/components/icons/Pentagon.tsx +++ b/packages/web/src/components/icons/Pentagon.tsx @@ -17,9 +17,9 @@ export default function Pentagon({ className, fill, stroke }: Props) { viewBox="-40.96 -40.96 593.93 593.93" transform="rotate(180)" stroke={fill} - stroke-width="0.005120100000000001" + strokeWidth="0.005120100000000001" > - + = { status: Status players: Player[] - setGameId: (gameId: string | null) => void - - setStatus: (name: K, data: T[K]) => void + setGameId: (_gameId: string | null) => void + setStatus: (_name: K, _data: T[K]) => void resetStatus: () => void + setPlayers: (_players: Player[]) => void - setPlayers: (players: Player[]) => void + reset: () => void } const initialStatus = createStatus("SHOW_ROOM", { text: "Waiting for the players", }) -export const useManagerStore = create>((set) => ({ +const initialState = { gameId: null, status: initialStatus, players: [], +} + +export const useManagerStore = create>((set) => ({ + ...initialState, setGameId: (gameId) => set({ gameId }), @@ -32,4 +35,6 @@ export const useManagerStore = create>((set) => ({ resetStatus: () => set({ status: initialStatus }), setPlayers: (players) => set({ players }), + + reset: () => set(initialState), })) diff --git a/packages/web/src/stores/player.tsx b/packages/web/src/stores/player.tsx index 2517947..a05b1e4 100644 --- a/packages/web/src/stores/player.tsx +++ b/packages/web/src/stores/player.tsx @@ -1,4 +1,3 @@ -/* eslint-disable no-unused-vars */ import { StatusDataMap } from "@rahoot/common/types/game/status" import { createStatus, Status } from "@rahoot/web/utils/createStatus" import { create } from "zustand" @@ -13,27 +12,30 @@ type PlayerStore = { player: PlayerState | null status: Status - setGameId: (gameId: string | null) => void + setGameId: (_gameId: string | null) => void - setPlayer: (state: PlayerState) => void - login: (gameId: string) => void - join: (username: string) => void - updatePoints: (points: number) => void - logout: () => void + setPlayer: (_state: PlayerState) => void + login: (_gameId: string) => void + join: (_username: string) => void + updatePoints: (_points: number) => void - setStatus: (name: K, data: T[K]) => void - resetStatus: () => void + setStatus: (_name: K, _data: T[K]) => void + + reset: () => void } const initialStatus = createStatus("WAIT", { text: "Waiting for the players", }) -export const usePlayerStore = create>((set) => ({ +const initialState = { gameId: null, player: null, status: initialStatus, - currentQuestion: null, +} + +export const usePlayerStore = create>((set) => ({ + ...initialState, setGameId: (gameId) => set({ gameId }), @@ -55,8 +57,7 @@ export const usePlayerStore = create>((set) => ({ player: { ...state.player, points }, })), - logout: () => set({ player: null }), - setStatus: (name, data) => set({ status: createStatus(name, data) }), - resetStatus: () => set({ status: initialStatus }), + + reset: () => set(initialState), })) diff --git a/packages/web/src/stores/question.tsx b/packages/web/src/stores/question.tsx index 6180ee3..033ba9b 100644 --- a/packages/web/src/stores/question.tsx +++ b/packages/web/src/stores/question.tsx @@ -1,10 +1,9 @@ -/* eslint-disable no-unused-vars */ import { GameUpdateQuestion } from "@rahoot/common/types/game" import { create } from "zustand" type QuestionStore = { questionStates: GameUpdateQuestion | null - setQuestionStates: (state: GameUpdateQuestion) => void + setQuestionStates: (_state: GameUpdateQuestion) => void } export const useQuestionStore = create((set) => ({ diff --git a/packages/web/src/utils/constants.ts b/packages/web/src/utils/constants.ts index ee5c04f..822b485 100644 --- a/packages/web/src/utils/constants.ts +++ b/packages/web/src/utils/constants.ts @@ -9,7 +9,7 @@ import Room from "@rahoot/web/components/game/states/Room" import Start from "@rahoot/web/components/game/states/Start" import Wait from "@rahoot/web/components/game/states/Wait" -import { Status } from "@rahoot/common/types/game/status" +import { STATUS } from "@rahoot/common/types/game/status" import Circle from "@rahoot/web/components/icons/Circle" import Rhombus from "@rahoot/web/components/icons/Rhombus" import Square from "@rahoot/web/components/icons/Square" @@ -26,7 +26,7 @@ export const ANSWERS_ICONS = [Triangle, Rhombus, Circle, Square] export const GAME_STATES = { status: { - name: Status.WAIT, + name: STATUS.WAIT, data: { text: "Waiting for the players" }, }, question: { @@ -36,20 +36,20 @@ export const GAME_STATES = { } export const GAME_STATE_COMPONENTS = { - [Status.SELECT_ANSWER]: Answers, - [Status.SHOW_QUESTION]: Question, - [Status.WAIT]: Wait, - [Status.SHOW_START]: Start, - [Status.SHOW_RESULT]: Result, - [Status.SHOW_PREPARED]: Prepared, + [STATUS.SELECT_ANSWER]: Answers, + [STATUS.SHOW_QUESTION]: Question, + [STATUS.WAIT]: Wait, + [STATUS.SHOW_START]: Start, + [STATUS.SHOW_RESULT]: Result, + [STATUS.SHOW_PREPARED]: Prepared, } export const GAME_STATE_COMPONENTS_MANAGER = { ...GAME_STATE_COMPONENTS, - [Status.SHOW_ROOM]: Room, - [Status.SHOW_RESPONSES]: Responses, - [Status.SHOW_LEADERBOARD]: Leaderboard, - [Status.FINISHED]: Podium, + [STATUS.SHOW_ROOM]: Room, + [STATUS.SHOW_RESPONSES]: Responses, + [STATUS.SHOW_LEADERBOARD]: Leaderboard, + [STATUS.FINISHED]: Podium, } export const SFX_ANSWERS_MUSIC = "/sounds/answersMusic.mp3" @@ -61,3 +61,16 @@ export const SFX_PODIUM_THREE = "/sounds/three.mp3" export const SFX_PODIUM_SECOND = "/sounds/second.mp3" export const SFX_PODIUM_FIRST = "/sounds/first.mp3" export const SFX_SNEAR_ROOL = "/sounds/snearRoll.mp3" + +export const MANAGER_SKIP_BTN = { + [STATUS.SHOW_ROOM]: "Start Game", + [STATUS.SHOW_START]: null, + [STATUS.SHOW_PREPARED]: null, + [STATUS.SHOW_QUESTION]: null, + [STATUS.SELECT_ANSWER]: "Skip", + [STATUS.SHOW_RESULT]: null, + [STATUS.SHOW_RESPONSES]: "Next", + [STATUS.SHOW_LEADERBOARD]: "Next", + [STATUS.FINISHED]: null, + [STATUS.WAIT]: null, +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4cb3b04..51b12c8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,15 +21,27 @@ importers: specifier: ^4.8.1 version: 4.8.1 zod: - specifier: ^3.22.4 + specifier: ^3.25.76 version: 3.25.76 devDependencies: + '@eslint/js': + specifier: ^9.38.0 + version: 9.38.0 '@types/node': - specifier: ^20.11.0 - version: 20.19.17 + specifier: ^20.19.22 + version: 20.19.22 + eslint: + specifier: ^9.38.0 + version: 9.38.0(jiti@2.6.1) + globals: + specifier: ^16.4.0 + version: 16.4.0 typescript: - specifier: ^5.3.3 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 + typescript-eslint: + specifier: ^8.46.1 + version: 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) packages/socket: dependencies: @@ -39,6 +51,9 @@ importers: '@t3-oss/env-core': specifier: ^0.13.8 version: 0.13.8(typescript@5.9.3)(zod@4.1.11) + dayjs: + specifier: ^1.11.18 + version: 1.11.18 socket.io: specifier: ^4.8.1 version: 4.8.1 @@ -49,12 +64,27 @@ importers: specifier: ^4.1.11 version: 4.1.11 devDependencies: + '@eslint/js': + specifier: ^9.38.0 + version: 9.38.0 + '@types/node': + specifier: ^24.8.1 + version: 24.8.1 esbuild: specifier: ^0.25.10 version: 0.25.10 + eslint: + specifier: ^9 + version: 9.36.0(jiti@2.6.1) + globals: + specifier: ^16.4.0 + version: 16.4.0 tsx: specifier: ^4.20.6 version: 4.20.6 + typescript-eslint: + specifier: ^8.46.1 + version: 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) packages/web: dependencies: @@ -66,13 +96,13 @@ importers: version: link:../socket '@t3-oss/env-nextjs': specifier: ^0.13.8 - version: 0.13.8(typescript@5.9.2)(zod@4.1.12) + version: 0.13.8(typescript@5.9.3)(zod@4.1.12) clsx: specifier: ^2.1.1 version: 2.1.1 ky: - specifier: ^1.11.0 - version: 1.11.0 + specifier: ^1.12.0 + version: 1.12.0 next: specifier: 15.5.4 version: 15.5.4(@babel/core@7.28.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -105,41 +135,35 @@ importers: version: 4.1.12 zustand: specifier: ^5.0.8 - version: 5.0.8(@types/react@19.1.15)(react@19.1.0) + version: 5.0.8(@types/react@19.2.2)(react@19.1.0) devDependencies: '@eslint/eslintrc': - specifier: ^3 + specifier: ^3.3.1 version: 3.3.1 '@tailwindcss/postcss': - specifier: ^4 - version: 4.1.13 + specifier: ^4.1.14 + version: 4.1.14 '@types/node': - specifier: ^20 - version: 20.19.17 + specifier: ^20.19.22 + version: 20.19.22 '@types/react': - specifier: ^19 - version: 19.1.15 + specifier: ^19.2.2 + version: 19.2.2 '@types/react-dom': - specifier: ^19 - version: 19.1.9(@types/react@19.1.15) - '@typescript-eslint/eslint-plugin': - specifier: ^8.45.0 - version: 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) - '@typescript-eslint/parser': - specifier: ^8.45.0 - version: 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + specifier: ^19.2.2 + version: 19.2.2(@types/react@19.2.2) eslint: - specifier: ^9 - version: 9.36.0(jiti@2.6.0) + specifier: ^9.38.0 + version: 9.38.0(jiti@2.6.1) eslint-config-next: specifier: 15.5.4 - version: 15.5.4(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + version: 15.5.4(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@9.36.0(jiti@2.6.0)) + version: 7.37.5(eslint@9.38.0(jiti@2.6.1)) eslint-plugin-react-hooks: specifier: ^6.1.1 - version: 6.1.1(eslint@9.36.0(jiti@2.6.0)) + version: 6.1.1(eslint@9.38.0(jiti@2.6.1)) globals: specifier: ^16.4.0 version: 16.4.0 @@ -150,11 +174,14 @@ importers: specifier: ^0.6.14 version: 0.6.14(prettier@3.6.2) tailwindcss: - specifier: ^4 - version: 4.1.13 + specifier: ^4.1.14 + version: 4.1.14 typescript: - specifier: ^5 - version: 5.9.2 + specifier: ^5.9.3 + version: 5.9.3 + typescript-eslint: + specifier: ^8.46.1 + version: 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) packages: @@ -408,14 +435,26 @@ packages: resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.3.1': resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.4.1': + resolution: {integrity: sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.15.2': resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.16.0': + resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -424,14 +463,26 @@ packages: resolution: {integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@9.38.0': + resolution: {integrity: sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/object-schema@2.1.6': resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/plugin-kit@0.3.5': resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/plugin-kit@0.4.0': + resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -670,8 +721,8 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@rushstack/eslint-patch@1.12.0': - resolution: {integrity: sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==} + '@rushstack/eslint-patch@1.14.0': + resolution: {integrity: sha512-WJFej426qe4RWOm9MMtP4V3CV4AucXolQty+GRgAWLgQXmpCuwzs7hEpxxhSc/znXUSxum9d/P/32MW0FlAAlA==} '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} @@ -713,65 +764,65 @@ packages: zod: optional: true - '@tailwindcss/node@4.1.13': - resolution: {integrity: sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==} + '@tailwindcss/node@4.1.14': + resolution: {integrity: sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==} - '@tailwindcss/oxide-android-arm64@4.1.13': - resolution: {integrity: sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==} + '@tailwindcss/oxide-android-arm64@4.1.14': + resolution: {integrity: sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.1.13': - resolution: {integrity: sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==} + '@tailwindcss/oxide-darwin-arm64@4.1.14': + resolution: {integrity: sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.1.13': - resolution: {integrity: sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==} + '@tailwindcss/oxide-darwin-x64@4.1.14': + resolution: {integrity: sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.1.13': - resolution: {integrity: sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==} + '@tailwindcss/oxide-freebsd-x64@4.1.14': + resolution: {integrity: sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13': - resolution: {integrity: sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14': + resolution: {integrity: sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.1.13': - resolution: {integrity: sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==} + '@tailwindcss/oxide-linux-arm64-gnu@4.1.14': + resolution: {integrity: sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.1.13': - resolution: {integrity: sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==} + '@tailwindcss/oxide-linux-arm64-musl@4.1.14': + resolution: {integrity: sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.1.13': - resolution: {integrity: sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==} + '@tailwindcss/oxide-linux-x64-gnu@4.1.14': + resolution: {integrity: sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.1.13': - resolution: {integrity: sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==} + '@tailwindcss/oxide-linux-x64-musl@4.1.14': + resolution: {integrity: sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-wasm32-wasi@4.1.13': - resolution: {integrity: sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==} + '@tailwindcss/oxide-wasm32-wasi@4.1.14': + resolution: {integrity: sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -782,24 +833,24 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.1.13': - resolution: {integrity: sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==} + '@tailwindcss/oxide-win32-arm64-msvc@4.1.14': + resolution: {integrity: sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.1.13': - resolution: {integrity: sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==} + '@tailwindcss/oxide-win32-x64-msvc@4.1.14': + resolution: {integrity: sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.1.13': - resolution: {integrity: sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==} + '@tailwindcss/oxide@4.1.14': + resolution: {integrity: sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==} engines: {node: '>= 10'} - '@tailwindcss/postcss@4.1.13': - resolution: {integrity: sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ==} + '@tailwindcss/postcss@4.1.14': + resolution: {integrity: sha512-BdMjIxy7HUNThK87C7BC8I1rE8BVUsfNQSI5siQ4JK3iIa3w0XyVvVL9SXLWO//CtYTcp1v7zci0fYwJOjB+Zg==} '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -816,74 +867,77 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/node@20.19.17': - resolution: {integrity: sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==} + '@types/node@20.19.22': + resolution: {integrity: sha512-hRnu+5qggKDSyWHlnmThnUqg62l29Aj/6vcYgUaSFL9oc7DVjeWEQN3PRgdSc6F8d9QRMWkf36CLMch1Do/+RQ==} - '@types/react-dom@19.1.9': - resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==} + '@types/node@24.8.1': + resolution: {integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==} + + '@types/react-dom@19.2.2': + resolution: {integrity: sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==} peerDependencies: - '@types/react': ^19.0.0 + '@types/react': ^19.2.0 - '@types/react@19.1.15': - resolution: {integrity: sha512-+kLxJpaJzXybyDyFXYADyP1cznTO8HSuBpenGlnKOAkH4hyNINiywvXS/tGJhsrGGP/gM185RA3xpjY0Yg4erA==} + '@types/react@19.2.2': + resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==} - '@typescript-eslint/eslint-plugin@8.45.0': - resolution: {integrity: sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==} + '@typescript-eslint/eslint-plugin@8.46.1': + resolution: {integrity: sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.45.0 + '@typescript-eslint/parser': ^8.46.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.45.0': - resolution: {integrity: sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==} + '@typescript-eslint/parser@8.46.1': + resolution: {integrity: sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.45.0': - resolution: {integrity: sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==} + '@typescript-eslint/project-service@8.46.1': + resolution: {integrity: sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.45.0': - resolution: {integrity: sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==} + '@typescript-eslint/scope-manager@8.46.1': + resolution: {integrity: sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.45.0': - resolution: {integrity: sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==} + '@typescript-eslint/tsconfig-utils@8.46.1': + resolution: {integrity: sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.45.0': - resolution: {integrity: sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==} + '@typescript-eslint/type-utils@8.46.1': + resolution: {integrity: sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.45.0': - resolution: {integrity: sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==} + '@typescript-eslint/types@8.46.1': + resolution: {integrity: sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.45.0': - resolution: {integrity: sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==} + '@typescript-eslint/typescript-estree@8.46.1': + resolution: {integrity: sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.45.0': - resolution: {integrity: sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==} + '@typescript-eslint/utils@8.46.1': + resolution: {integrity: sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.45.0': - resolution: {integrity: sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==} + '@typescript-eslint/visitor-keys@8.46.1': + resolution: {integrity: sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -1052,8 +1106,8 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axe-core@4.10.3: - resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} + axe-core@4.11.0: + resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==} engines: {node: '>=4'} axobject-query@4.1.0: @@ -1067,8 +1121,8 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - baseline-browser-mapping@2.8.12: - resolution: {integrity: sha512-vAPMQdnyKCBtkmQA6FMCBvU9qFIppS3nzyXnEM+Lo2IAhG4Mpjv9cCxMudhgV3YdNNJv6TNqXy97dfRVL2LmaQ==} + baseline-browser-mapping@2.8.18: + resolution: {integrity: sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w==} hasBin: true brace-expansion@1.1.12: @@ -1102,11 +1156,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001745: - resolution: {integrity: sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==} - - caniuse-lite@1.0.30001747: - resolution: {integrity: sha512-mzFa2DGIhuc5490Nd/G31xN1pnBnYMadtkyTjefPI7wzypqgCEpeWu9bJr0OnDsyKrW75zA9ZAt7pbQFmwLsQg==} + caniuse-lite@1.0.30001751: + resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -1166,6 +1217,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + dayjs@1.11.18: + resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==} + debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -1203,8 +1257,8 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - detect-libc@2.1.1: - resolution: {integrity: sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} doctrine@2.1.0: @@ -1231,8 +1285,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.230: - resolution: {integrity: sha512-A6A6Fd3+gMdaed9wX83CvHYJb4UuapPD5X5SLq72VZJzxHSY0/LUweGXRWmQlh2ln7KV7iw7jnwXK7dlPoOnHQ==} + electron-to-chromium@1.5.237: + resolution: {integrity: sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} @@ -1399,6 +1453,16 @@ packages: jiti: optional: true + eslint@9.38.0: + resolution: {integrity: sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + espree@10.4.0: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1486,6 +1550,10 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -1505,6 +1573,9 @@ packages: get-tsconfig@4.10.1: resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + get-tsconfig@4.12.0: + resolution: {integrity: sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1525,8 +1596,8 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} - goober@2.1.16: - resolution: {integrity: sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==} + goober@2.1.18: + resolution: {integrity: sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==} peerDependencies: csstype: ^3.0.10 @@ -1633,8 +1704,8 @@ packages: resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} engines: {node: '>= 0.4'} - is-generator-function@1.1.0: - resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} engines: {node: '>= 0.4'} is-glob@4.0.3: @@ -1703,8 +1774,8 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} - jiti@2.6.0: - resolution: {integrity: sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==} + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true js-tokens@4.0.0: @@ -1744,8 +1815,8 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - ky@1.11.0: - resolution: {integrity: sha512-NEyo0ICpS0cqSuyoJFMCnHOZJILqXsKhIZlHJGDYaH8OB5IFrGzuBpEwyoMZG6gUKMPrazH30Ax5XKaujvD8ag==} + ky@1.12.0: + resolution: {integrity: sha512-YRLmSUHCwOJRBMArtqMRLOmO7fewn3yOoui6aB8ERkRVXupa0UiaQaKbIXteMt4jUElhbdqTMsLFHs8APxxUoQ==} engines: {node: '>=18'} language-subtag-registry@0.3.23: @@ -1886,8 +1957,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - napi-postinstall@0.3.3: - resolution: {integrity: sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==} + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} hasBin: true @@ -1919,8 +1990,8 @@ packages: sass: optional: true - node-releases@2.0.23: - resolution: {integrity: sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==} + node-releases@2.0.25: + resolution: {integrity: sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -2171,6 +2242,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -2289,11 +2365,11 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tailwindcss@4.1.13: - resolution: {integrity: sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==} + tailwindcss@4.1.14: + resolution: {integrity: sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==} - tapable@2.2.3: - resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==} + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} tar@7.5.1: @@ -2358,10 +2434,12 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typescript@5.9.2: - resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} - engines: {node: '>=14.17'} - hasBin: true + typescript-eslint@8.46.1: + resolution: {integrity: sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} @@ -2375,6 +2453,9 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.14.0: + resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} + unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} @@ -2686,9 +2767,14 @@ snapshots: '@esbuild/win32-x64@0.25.10': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.0))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.1))': dependencies: - eslint: 9.36.0(jiti@2.6.0) + eslint: 9.36.0(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/eslint-utils@4.9.0(eslint@9.38.0(jiti@2.6.1))': + dependencies: + eslint: 9.38.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -2701,12 +2787,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/config-array@0.21.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + '@eslint/config-helpers@0.3.1': {} + '@eslint/config-helpers@0.4.1': + dependencies: + '@eslint/core': 0.16.0 + '@eslint/core@0.15.2': dependencies: '@types/json-schema': 7.0.15 + '@eslint/core@0.16.0': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 @@ -2723,13 +2825,22 @@ snapshots: '@eslint/js@9.36.0': {} + '@eslint/js@9.38.0': {} + '@eslint/object-schema@2.1.6': {} + '@eslint/object-schema@2.1.7': {} + '@eslint/plugin-kit@0.3.5': dependencies: '@eslint/core': 0.15.2 levn: 0.4.1 + '@eslint/plugin-kit@0.4.0': + dependencies: + '@eslint/core': 0.16.0 + levn: 0.4.1 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -2906,7 +3017,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/eslint-patch@1.12.0': {} + '@rushstack/eslint-patch@1.14.0': {} '@socket.io/component-emitter@3.1.2': {} @@ -2914,94 +3025,94 @@ snapshots: dependencies: tslib: 2.8.1 - '@t3-oss/env-core@0.13.8(typescript@5.9.2)(zod@4.1.12)': - optionalDependencies: - typescript: 5.9.2 - zod: 4.1.12 - '@t3-oss/env-core@0.13.8(typescript@5.9.3)(zod@4.1.11)': optionalDependencies: typescript: 5.9.3 zod: 4.1.11 - '@t3-oss/env-nextjs@0.13.8(typescript@5.9.2)(zod@4.1.12)': - dependencies: - '@t3-oss/env-core': 0.13.8(typescript@5.9.2)(zod@4.1.12) + '@t3-oss/env-core@0.13.8(typescript@5.9.3)(zod@4.1.12)': optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 zod: 4.1.12 - '@tailwindcss/node@4.1.13': + '@t3-oss/env-nextjs@0.13.8(typescript@5.9.3)(zod@4.1.12)': + dependencies: + '@t3-oss/env-core': 0.13.8(typescript@5.9.3)(zod@4.1.12) + optionalDependencies: + typescript: 5.9.3 + zod: 4.1.12 + + '@tailwindcss/node@4.1.14': dependencies: '@jridgewell/remapping': 2.3.5 enhanced-resolve: 5.18.3 - jiti: 2.6.0 + jiti: 2.6.1 lightningcss: 1.30.1 magic-string: 0.30.19 source-map-js: 1.2.1 - tailwindcss: 4.1.13 + tailwindcss: 4.1.14 - '@tailwindcss/oxide-android-arm64@4.1.13': + '@tailwindcss/oxide-android-arm64@4.1.14': optional: true - '@tailwindcss/oxide-darwin-arm64@4.1.13': + '@tailwindcss/oxide-darwin-arm64@4.1.14': optional: true - '@tailwindcss/oxide-darwin-x64@4.1.13': + '@tailwindcss/oxide-darwin-x64@4.1.14': optional: true - '@tailwindcss/oxide-freebsd-x64@4.1.13': + '@tailwindcss/oxide-freebsd-x64@4.1.14': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.1.13': + '@tailwindcss/oxide-linux-arm64-gnu@4.1.14': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.1.13': + '@tailwindcss/oxide-linux-arm64-musl@4.1.14': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.1.13': + '@tailwindcss/oxide-linux-x64-gnu@4.1.14': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.1.13': + '@tailwindcss/oxide-linux-x64-musl@4.1.14': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.1.13': + '@tailwindcss/oxide-wasm32-wasi@4.1.14': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.1.13': + '@tailwindcss/oxide-win32-arm64-msvc@4.1.14': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.1.13': + '@tailwindcss/oxide-win32-x64-msvc@4.1.14': optional: true - '@tailwindcss/oxide@4.1.13': + '@tailwindcss/oxide@4.1.14': dependencies: - detect-libc: 2.1.1 + detect-libc: 2.1.2 tar: 7.5.1 optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.13 - '@tailwindcss/oxide-darwin-arm64': 4.1.13 - '@tailwindcss/oxide-darwin-x64': 4.1.13 - '@tailwindcss/oxide-freebsd-x64': 4.1.13 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.13 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.13 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.13 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.13 - '@tailwindcss/oxide-linux-x64-musl': 4.1.13 - '@tailwindcss/oxide-wasm32-wasi': 4.1.13 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.13 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.13 + '@tailwindcss/oxide-android-arm64': 4.1.14 + '@tailwindcss/oxide-darwin-arm64': 4.1.14 + '@tailwindcss/oxide-darwin-x64': 4.1.14 + '@tailwindcss/oxide-freebsd-x64': 4.1.14 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.14 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.14 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.14 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.14 + '@tailwindcss/oxide-linux-x64-musl': 4.1.14 + '@tailwindcss/oxide-wasm32-wasi': 4.1.14 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.14 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.14 - '@tailwindcss/postcss@4.1.13': + '@tailwindcss/postcss@4.1.14': dependencies: '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.1.13 - '@tailwindcss/oxide': 4.1.13 + '@tailwindcss/node': 4.1.14 + '@tailwindcss/oxide': 4.1.14 postcss: 8.5.6 - tailwindcss: 4.1.13 + tailwindcss: 4.1.14 '@tybys/wasm-util@0.10.1': dependencies: @@ -3010,7 +3121,7 @@ snapshots: '@types/cors@2.8.19': dependencies: - '@types/node': 20.19.17 + '@types/node': 20.19.22 '@types/estree@1.0.8': {} @@ -3018,109 +3129,165 @@ snapshots: '@types/json5@0.0.29': {} - '@types/node@20.19.17': + '@types/node@20.19.22': dependencies: undici-types: 6.21.0 - '@types/react-dom@19.1.9(@types/react@19.1.15)': + '@types/node@24.8.1': dependencies: - '@types/react': 19.1.15 + undici-types: 7.14.0 - '@types/react@19.1.15': + '@types/react-dom@19.2.2(@types/react@19.2.2)': + dependencies: + '@types/react': 19.2.2 + + '@types/react@19.2.2': dependencies: csstype: 3.1.3 - '@typescript-eslint/eslint-plugin@8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/type-utils': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.45.0 - eslint: 9.36.0(jiti@2.6.0) + '@typescript-eslint/parser': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.1 + '@typescript-eslint/type-utils': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.1 + eslint: 9.36.0(jiti@2.6.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.45.0 + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.1 + '@typescript-eslint/type-utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.1 + eslint: 9.38.0(jiti@2.6.1) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.46.1 + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.1 debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.0) - typescript: 5.9.2 + eslint: 9.36.0(jiti@2.6.1) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.45.0(typescript@5.9.2)': + '@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.2) - '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/scope-manager': 8.46.1 + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.1 debug: 4.4.3 - typescript: 5.9.2 + eslint: 9.38.0(jiti@2.6.1) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.45.0': + '@typescript-eslint/project-service@8.46.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/visitor-keys': 8.45.0 - - '@typescript-eslint/tsconfig-utils@8.45.0(typescript@5.9.2)': - dependencies: - typescript: 5.9.2 - - '@typescript-eslint/type-utils@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)': - dependencies: - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3) + '@typescript-eslint/types': 8.46.1 debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.0) - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.45.0': {} - - '@typescript-eslint/typescript-estree@8.45.0(typescript@5.9.2)': + '@typescript-eslint/scope-manager@8.46.1': dependencies: - '@typescript-eslint/project-service': 8.45.0(typescript@5.9.2) - '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.2) - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/visitor-keys': 8.45.0 + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/visitor-keys': 8.46.1 + + '@typescript-eslint/tsconfig-utils@8.46.1(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.1) + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/type-utils@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.38.0(jiti@2.6.1) + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.46.1': {} + + '@typescript-eslint/typescript-estree@8.46.1(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.46.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3) + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/visitor-keys': 8.46.1 debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.2 - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)': + '@typescript-eslint/utils@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0)) - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) - eslint: 9.36.0(jiti@2.6.0) - typescript: 5.9.2 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.46.1 + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + eslint: 9.36.0(jiti@2.6.1) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.45.0': + '@typescript-eslint/utils@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.45.0 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.46.1 + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + eslint: 9.38.0(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.46.1': + dependencies: + '@typescript-eslint/types': 8.46.1 eslint-visitor-keys: 4.2.1 '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -3283,7 +3450,7 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - axe-core@4.10.3: {} + axe-core@4.11.0: {} axobject-query@4.1.0: {} @@ -3291,7 +3458,7 @@ snapshots: base64id@2.0.0: {} - baseline-browser-mapping@2.8.12: {} + baseline-browser-mapping@2.8.18: {} brace-expansion@1.1.12: dependencies: @@ -3308,10 +3475,10 @@ snapshots: browserslist@4.26.3: dependencies: - baseline-browser-mapping: 2.8.12 - caniuse-lite: 1.0.30001747 - electron-to-chromium: 1.5.230 - node-releases: 2.0.23 + baseline-browser-mapping: 2.8.18 + caniuse-lite: 1.0.30001751 + electron-to-chromium: 1.5.237 + node-releases: 2.0.25 update-browserslist-db: 1.1.3(browserslist@4.26.3) call-bind-apply-helpers@1.0.2: @@ -3333,9 +3500,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001745: {} - - caniuse-lite@1.0.30001747: {} + caniuse-lite@1.0.30001751: {} chalk@4.1.2: dependencies: @@ -3393,6 +3558,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + dayjs@1.11.18: {} + debug@3.2.7: dependencies: ms: 2.1.3 @@ -3419,7 +3586,7 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 - detect-libc@2.1.1: {} + detect-libc@2.1.2: {} doctrine@2.1.0: dependencies: @@ -3446,7 +3613,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.230: {} + electron-to-chromium@1.5.237: {} emoji-regex@9.2.2: {} @@ -3467,7 +3634,7 @@ snapshots: engine.io@6.6.4: dependencies: '@types/cors': 2.8.19 - '@types/node': 20.19.17 + '@types/node': 20.19.22 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -3483,7 +3650,7 @@ snapshots: enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 - tapable: 2.2.3 + tapable: 2.3.0 es-abstract@1.24.0: dependencies: @@ -3619,21 +3786,21 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-next@15.5.4(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2): + eslint-config-next@15.5.4(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3): dependencies: '@next/eslint-plugin-next': 15.5.4 - '@rushstack/eslint-patch': 1.12.0 - '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) - eslint: 9.36.0(jiti@2.6.0) + '@rushstack/eslint-patch': 1.14.0 + '@typescript-eslint/eslint-plugin': 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.38.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.0)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.36.0(jiti@2.6.0)) - eslint-plugin-react: 7.37.5(eslint@9.36.0(jiti@2.6.0)) - eslint-plugin-react-hooks: 5.2.0(eslint@9.36.0(jiti@2.6.0)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.38.0(jiti@2.6.1)) + eslint-plugin-react: 7.37.5(eslint@9.38.0(jiti@2.6.1)) + eslint-plugin-react-hooks: 5.2.0(eslint@9.38.0(jiti@2.6.1)) optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - eslint-import-resolver-webpack - eslint-plugin-import-x @@ -3647,33 +3814,33 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.0)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.0) - get-tsconfig: 4.10.1 + eslint: 9.38.0(jiti@2.6.1) + get-tsconfig: 4.12.0 is-bun-module: 2.0.0 stable-hash: 0.0.5 tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) - eslint: 9.36.0(jiti@2.6.0) + '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.38.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.0)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -3682,9 +3849,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.36.0(jiti@2.6.0) + eslint: 9.38.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.36.0(jiti@2.6.0)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -3696,23 +3863,23 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) + '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.36.0(jiti@2.6.0)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.38.0(jiti@2.6.1)): dependencies: aria-query: 5.3.2 array-includes: 3.1.9 array.prototype.flatmap: 1.3.3 ast-types-flow: 0.0.8 - axe-core: 4.10.3 + axe-core: 4.11.0 axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.36.0(jiti@2.6.0) + eslint: 9.38.0(jiti@2.6.1) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -3721,21 +3888,21 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-react-hooks@5.2.0(eslint@9.36.0(jiti@2.6.0)): + eslint-plugin-react-hooks@5.2.0(eslint@9.38.0(jiti@2.6.1)): dependencies: - eslint: 9.36.0(jiti@2.6.0) + eslint: 9.38.0(jiti@2.6.1) - eslint-plugin-react-hooks@6.1.1(eslint@9.36.0(jiti@2.6.0)): + eslint-plugin-react-hooks@6.1.1(eslint@9.38.0(jiti@2.6.1)): dependencies: '@babel/core': 7.28.4 '@babel/parser': 7.28.4 - eslint: 9.36.0(jiti@2.6.0) + eslint: 9.38.0(jiti@2.6.1) zod: 4.1.12 zod-validation-error: 4.0.2(zod@4.1.12) transitivePeerDependencies: - supports-color - eslint-plugin-react@7.37.5(eslint@9.36.0(jiti@2.6.0)): + eslint-plugin-react@7.37.5(eslint@9.38.0(jiti@2.6.1)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -3743,7 +3910,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.36.0(jiti@2.6.0) + eslint: 9.38.0(jiti@2.6.1) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -3766,9 +3933,9 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.36.0(jiti@2.6.0): + eslint@9.36.0(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 '@eslint/config-helpers': 0.3.1 @@ -3804,7 +3971,48 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: - jiti: 2.6.0 + jiti: 2.6.1 + transitivePeerDependencies: + - supports-color + + eslint@9.38.0(jiti@2.6.1): + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.1 + '@eslint/core': 0.16.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.38.0 + '@eslint/plugin-kit': 0.4.0 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 transitivePeerDependencies: - supports-color @@ -3896,6 +4104,8 @@ snapshots: functions-have-names@1.2.3: {} + generator-function@2.0.1: {} + gensync@1.0.0-beta.2: {} get-intrinsic@1.3.0: @@ -3926,6 +4136,10 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + get-tsconfig@4.12.0: + dependencies: + resolve-pkg-maps: 1.0.0 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -3943,7 +4157,7 @@ snapshots: define-properties: 1.2.1 gopd: 1.2.0 - goober@2.1.16(csstype@3.1.3): + goober@2.1.18(csstype@3.1.3): dependencies: csstype: 3.1.3 @@ -4019,7 +4233,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 is-callable@1.2.7: {} @@ -4044,9 +4258,10 @@ snapshots: dependencies: call-bound: 1.0.4 - is-generator-function@1.1.0: + is-generator-function@1.1.2: dependencies: call-bound: 1.0.4 + generator-function: 2.0.1 get-proto: 1.0.1 has-tostringtag: 1.0.2 safe-regex-test: 1.1.0 @@ -4118,7 +4333,7 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 - jiti@2.6.0: {} + jiti@2.6.1: {} js-tokens@4.0.0: {} @@ -4151,7 +4366,7 @@ snapshots: dependencies: json-buffer: 3.0.1 - ky@1.11.0: {} + ky@1.12.0: {} language-subtag-registry@0.3.23: {} @@ -4196,7 +4411,7 @@ snapshots: lightningcss@1.30.1: dependencies: - detect-libc: 2.1.1 + detect-libc: 2.1.2 optionalDependencies: lightningcss-darwin-arm64: 1.30.1 lightningcss-darwin-x64: 1.30.1 @@ -4262,7 +4477,7 @@ snapshots: nanoid@3.3.11: {} - napi-postinstall@0.3.3: {} + napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} @@ -4272,7 +4487,7 @@ snapshots: dependencies: '@next/env': 15.5.4 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001745 + caniuse-lite: 1.0.30001751 postcss: 8.4.31 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -4291,7 +4506,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - node-releases@2.0.23: {} + node-releases@2.0.25: {} object-assign@4.1.1: {} @@ -4421,7 +4636,7 @@ snapshots: react-hot-toast@2.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: csstype: 3.1.3 - goober: 2.1.16(csstype@3.1.3) + goober: 2.1.18(csstype@3.1.3) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -4496,6 +4711,8 @@ snapshots: semver@7.7.2: {} + semver@7.7.3: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -4521,8 +4738,8 @@ snapshots: sharp@0.34.4: dependencies: '@img/colour': 1.0.0 - detect-libc: 2.1.1 - semver: 7.7.2 + detect-libc: 2.1.2 + semver: 7.7.3 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.4 '@img/sharp-darwin-x64': 0.34.4 @@ -4699,9 +4916,9 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tailwindcss@4.1.13: {} + tailwindcss@4.1.14: {} - tapable@2.2.3: {} + tapable@2.3.0: {} tar@7.5.1: dependencies: @@ -4724,9 +4941,9 @@ snapshots: toposort@2.0.2: {} - ts-api-utils@2.1.0(typescript@5.9.2): + ts-api-utils@2.1.0(typescript@5.9.3): dependencies: - typescript: 5.9.2 + typescript: 5.9.3 tsconfig-paths@3.15.0: dependencies: @@ -4785,7 +5002,27 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript@5.9.2: {} + typescript-eslint@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.36.0(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + typescript-eslint@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.38.0(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color typescript@5.9.3: {} @@ -4798,9 +5035,11 @@ snapshots: undici-types@6.21.0: {} + undici-types@7.14.0: {} + unrs-resolver@1.11.1: dependencies: - napi-postinstall: 0.3.3 + napi-postinstall: 0.3.4 optionalDependencies: '@unrs/resolver-binding-android-arm-eabi': 1.11.1 '@unrs/resolver-binding-android-arm64': 1.11.1 @@ -4857,7 +5096,7 @@ snapshots: is-async-function: 2.1.1 is-date-object: 1.1.0 is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.0 + is-generator-function: 1.1.2 is-regex: 1.2.1 is-weakref: 1.1.1 isarray: 2.0.5 @@ -4915,7 +5154,7 @@ snapshots: zod@4.1.12: {} - zustand@5.0.8(@types/react@19.1.15)(react@19.1.0): + zustand@5.0.8(@types/react@19.2.2)(react@19.1.0): optionalDependencies: - '@types/react': 19.1.15 + '@types/react': 19.2.2 react: 19.1.0 From 90555891f8308bd04ebcd8fa3139fc4b21b991ba Mon Sep 17 00:00:00 2001 From: Ralex <95540504+Ralex91@users.noreply.github.com> Date: Sun, 19 Oct 2025 12:32:46 +0200 Subject: [PATCH 04/17] fix(docker): fix config files reading & add compose file --- .env.example | 2 +- Dockerfile | 1 + compose.yml | 13 ++++++++ packages/config/game.json | 4 --- packages/config/quizz/example.json | 41 -------------------------- packages/socket/src/env.ts | 2 ++ packages/socket/src/index.ts | 8 +++-- packages/socket/src/services/config.ts | 6 +++- packages/web/package.json | 2 +- 9 files changed, 29 insertions(+), 50 deletions(-) create mode 100644 compose.yml delete mode 100644 packages/config/game.json delete mode 100644 packages/config/quizz/example.json diff --git a/.env.example b/.env.example index dc87529..37b9549 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,2 @@ +WEB_ORIGIN=http://localhost:3000 # Default: http://localhost:3000, for allow all origins use '*' SOCKET_URL=http://localhost:3001 # Default: http://localhost:3001 -SOCKER_PORT=3001 # Default: 3001 diff --git a/Dockerfile b/Dockerfile index cb58f84..92e640c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -67,6 +67,7 @@ EXPOSE 3000 5505 # Environment variables ENV NODE_ENV=production +ENV CONFIG_PATH=/app/config # Start both services (Next.js web app + Socket server) CMD ["sh", "-c", "node packages/web/server.js & node packages/socket/dist/index.cjs"] diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..46701b8 --- /dev/null +++ b/compose.yml @@ -0,0 +1,13 @@ +version: "3.8" + +services: + rahoot: + image: rahoot + ports: + - "3000:3000" + - "3001:3001" + volumes: + - ./config:/app/config # Path to your game config + environment: + - WEB_ORIGIN=http://localhost:3000 + - SOCKET_URL=http://localhost:3001 diff --git a/packages/config/game.json b/packages/config/game.json deleted file mode 100644 index 66f12d9..0000000 --- a/packages/config/game.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "managerPassword": "PASSWORD", - "music": true -} \ No newline at end of file diff --git a/packages/config/quizz/example.json b/packages/config/quizz/example.json deleted file mode 100644 index c048d43..0000000 --- a/packages/config/quizz/example.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "subject": "Example Quizz", - "questions": [ - { - "question": "What is good answer ?", - "answers": [ - "No", - "Good answer", - "No", - "No" - ], - "solution": 1, - "cooldown": 5, - "time": 15 - }, - { - "question": "What is good answer with image ?", - "answers": [ - "No", - "No", - "No", - "Good answer" - ], - "image": "https://placehold.co/600x400.png", - "solution": 3, - "cooldown": 5, - "time": 20 - }, - { - "question": "What is good answer with two answers ?", - "answers": [ - "Good answer", - "No" - ], - "image": "https://placehold.co/600x400.png", - "solution": 0, - "cooldown": 5, - "time": 20 - } - ] -} \ No newline at end of file diff --git a/packages/socket/src/env.ts b/packages/socket/src/env.ts index b64a0ab..3be0d1d 100644 --- a/packages/socket/src/env.ts +++ b/packages/socket/src/env.ts @@ -3,10 +3,12 @@ import { z } from "zod/v4" const env = createEnv({ server: { + WEB_ORIGIN: z.string().optional().default("http://localhost:3000"), SOCKER_PORT: z.string().optional().default("3001"), }, runtimeEnv: { + WEB_ORIGIN: process.env.WEB_ORIGIN, SOCKER_PORT: process.env.SOCKER_PORT, }, }) diff --git a/packages/socket/src/index.ts b/packages/socket/src/index.ts index 646831e..ae25428 100644 --- a/packages/socket/src/index.ts +++ b/packages/socket/src/index.ts @@ -7,11 +7,15 @@ import Registry from "@rahoot/socket/services/registry" import { withGame } from "@rahoot/socket/utils/game" import { Server as ServerIO } from "socket.io" -const io: Server = new ServerIO() +const io: Server = new ServerIO({ + cors: { + origin: [env.WEB_ORIGIN], + }, +}) Config.init() const registry = Registry.getInstance() -const port = env.SOCKER_PORT || 3001 +const port = 3001 console.log(`Socket server running on port ${port}`) io.listen(Number(port)) diff --git a/packages/socket/src/services/config.ts b/packages/socket/src/services/config.ts index e052542..92db828 100644 --- a/packages/socket/src/services/config.ts +++ b/packages/socket/src/services/config.ts @@ -2,8 +2,12 @@ import { QuizzWithId } from "@rahoot/common/types/game" import fs from "fs" import { resolve } from "path" +const inContainerPath = process.env.CONFIG_PATH + const getPath = (path: string = "") => - resolve(process.cwd(), "../../config", path) + inContainerPath + ? resolve(inContainerPath, path) + : resolve(process.cwd(), "../../config", path) class Config { static init() { diff --git a/packages/web/package.json b/packages/web/package.json index 7d547d7..5f9c43b 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -4,7 +4,7 @@ "scripts": { "dev": "next dev", "build": "next build", - "start": "node .next/standalone/packages/web/server.js", + "start": "next start", "lint": "eslint" }, "dependencies": { From 46c43846e998c5eb3ebff3e7e2e71bf444b566c5 Mon Sep 17 00:00:00 2001 From: Ralex <95540504+Ralex91@users.noreply.github.com> Date: Sat, 25 Oct 2025 13:41:29 +0200 Subject: [PATCH 05/17] feat(docker): update Dockerfile and compose configuration, enhance README for deployment methods --- .github/workflows/docker-release.yml | 69 +++++++ .gitignore | 4 +- Dockerfile | 4 +- README.md | 192 +++++++++++------- compose.yml | 2 +- .../src/app/game/manager/[gameId]/page.tsx | 1 - .../web/src/components/game/states/Podium.tsx | 2 - 7 files changed, 198 insertions(+), 76 deletions(-) create mode 100644 .github/workflows/docker-release.yml diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml new file mode 100644 index 0000000..e8d68fa --- /dev/null +++ b/.github/workflows/docker-release.yml @@ -0,0 +1,69 @@ +name: Docker Release +on: + release: + types: [published] + +env: + DOCKER_PLATFORMS: | + linux/amd64 + linux/arm64 + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Extract version and tags + run: | + if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then + VERSION=${GITHUB_REF_NAME#v} + echo "VERSION=$VERSION" >> $GITHUB_ENV + + # Extract major.minor (ex: 1.2.3 -> 1.2) + MAJOR_MINOR=$(echo $VERSION | cut -d. -f1,2) + echo "MAJOR_MINOR=$MAJOR_MINOR" >> $GITHUB_ENV + else + echo "VERSION=latest" >> $GITHUB_ENV + echo "MAJOR_MINOR=latest" >> $GITHUB_ENV + fi + + - name: Extract repository name (lowercase) + run: echo "REPO_NAME=$(basename ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: ${{ env.DOCKER_PLATFORMS }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + version: latest + install: true + platforms: ${{ env.DOCKER_PLATFORMS }} + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + platforms: ${{ env.DOCKER_PLATFORMS }} + push: true + tags: | + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:${{ env.VERSION }} + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:${{ env.MAJOR_MINOR }} + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:latest + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + BUILDKIT_INLINE_CACHE=1 diff --git a/.gitignore b/.gitignore index 7af7f04..ed1665d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /node_modules -.env \ No newline at end of file +.env +.secrets +release.json \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 92e640c..02bec79 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:24-alpine AS base +FROM node:22-alpine AS base # Enable and prepare pnpm via Corepack RUN corepack enable && corepack prepare pnpm@latest --activate @@ -37,7 +37,7 @@ WORKDIR /app/packages/socket RUN if [ -f "tsconfig.json" ]; then pnpm build; fi # ----- RUNNER ----- -FROM node:24-alpine AS runner +FROM node:22-alpine AS runner WORKDIR /app # Create a non-root user for better security diff --git a/README.md b/README.md index 93772a0..250b303 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@


- +

+ Visitor Badge + Docker Pulls +

## 🧩 What is this project? @@ -12,93 +15,144 @@ Rahoot is a straightforward and open-source clone of the Kahoot! platform, allow ## ⚙️ Prerequisites -- Node.js version 20 or higher +Choose one of the following deployment methods: + +### Without Docker + +- Node.js : version 20 or higher +- PNPM : Learn more about [here](https://pnpm.io/) + +### With Docker + +- Docker and Docker Compose ## 📖 Getting Started -1. #### Clone the GitHub repository of your project. - ```bash - git clone https://github.com/Ralex91/Rahoot.git - cd ./Rahoot - ``` -2. #### Install the dependencies using your preferred package manager +Choose your deployment method: - ```bash - npm install - ``` +### 🐳 Using Docker (Recommended) -
-
+Using Docker Compose (recommended): -## 📦 Running the Application in Production Mode: - -1. #### Check websocket connfiguration in [config.mjs](config.mjs) - - If you want the client to connect directly to the websocket server, edit the [config.mjs](config.mjs) file and change the localhost to your public IP address. - - ```js - export const WEBSOCKET_PUBLIC_URL = "http://1.2.3.4:3100/" - export const WEBSOCKET_SERVER_PORT = 3100 - - // Rest of the config ... - ``` - -2. #### Start the application - - ```bash - npm run all - ``` - -## ⚙️ Running the Application in Development Mode: +You can find the docker compose configuration in the repository: +[docker-compose.yml](/compose.yml) ```bash -npm run all-dev +docker compose up -d ``` -## 🔧 Configuration +Or using Docker directly: -Configuration can be found in [config.mjs](config.mjs) +```bash +docker run -d \ + -p 3000:3000 \ + -p 3001:3001 \ + -v ./config:/app/config \ + -e WEB_ORIGIN=http://localhost:3000 \ + -e SOCKET_URL=http://localhost:3001 \ + ralex91/rahoot:latest +``` -```js -const QUIZZ_CONFIG = { - password: "PASSWORD", // Manager password - subject: "Adobe", // Subject of the quiz - questions: [ - { // Example question - question: "What is good answer ?", // Question - answers: [ // Possible answers - "No", - "Yes", - "No", - "No", - ], - image: - "https://images.unsplash.com/....", // Image URL (optional) - solution: 1, // Index of the correct answer (index starts at 0) - cooldown: 5, // Show question cooldown in seconds - time: 15, // Time to answer in seconds - }, - ... - ], +The application will be available at: + +- Web Interface: http://localhost:3000 +- WebSocket Server: ws://localhost:3001 + +### 🛠️ Without Docker + +1. Clone the repository: + +```bash +git clone https://github.com/Ralex91/Rahoot.git +cd ./Rahoot +``` + +2. Install dependencies: + +```bash +pnpm install +``` + +3. Change the environment variables in the `.env` file + +4. Build and start the application: + +```bash +# Development mode +pnpm run dev + +# Production mode +pnpm run build +pnpm start +``` + +## ⚙️ Configuration + +The configuration is split into two main parts: + +### 1. Game Configuration (`config/game.json`) + +Main game settings: + +```json +{ + "managerPassword": "PASSWORD", + "music": true } ``` -## 🤔 How to use +Options: -- Go to [https://localhost:3000/manager](https://localhost:3000/manager) enter manager password. +- `managerPassword`: The master password for accessing the manager interface +- `music`: Enable/disable game music -- Share link [https://localhost:3000/](https://localhost:3000/) and code on manager screen with your friends and get ready to play. +### 2. Quiz Configuration (`config/quizz/*.json`) -- Once everyone is ready, start the game with button on the top left of the screen of manager. +Create your quiz files in the `config/quizz/` directory. You can have multiple quiz files and select which one to use when starting a game. + +Example quiz configuration (`config/quizz/example.json`): + +```json +{ + "subject": "Example Quiz", + "questions": [ + { + "question": "What is the correct answer?", + "answers": ["No", "Yes", "No", "No"], + "image": "https://images.unsplash.com/....", + "solution": 1, + "cooldown": 5, + "time": 15 + } + ] +} +``` + +Quiz Options: + +- `subject`: Title/topic of the quiz +- `questions`: Array of question objects containing: + - `question`: The question text + - `answers`: Array of possible answers (2-4 options) + - `image`: Optional URL for question image + - `solution`: Index of correct answer (0-based) + - `cooldown`: Time in seconds before showing the question + - `time`: Time in seconds allowed to answer + +## 🎮 How to Play + +1. Access the manager interface at http://localhost:3000/manager +2. Enter the manager password (defined in quiz config) +3. Share the game URL (http://localhost:3000) and room code with participants +4. Wait for players to join +5. Click the start button to begin the game ## 📝 Contributing -- Create a fork +1. Fork the repository +2. Create a new branch (e.g., `feat/my-feature`) +3. Make your changes +4. Create a pull request +5. Wait for review and merge -- Create work branch (Example: githubUsername/featureName). - -- Commit and push your changes in the work branch. - -- Open a pull request. - -- Your pull request would be merged and changes will be reflected in the main repository. +For bug reports or feature requests, please [create an issue](https://github.com/Ralex91/Rahoot/issues). diff --git a/compose.yml b/compose.yml index 46701b8..8db2259 100644 --- a/compose.yml +++ b/compose.yml @@ -2,7 +2,7 @@ version: "3.8" services: rahoot: - image: rahoot + image: ralex91/rahoot:latest ports: - "3000:3000" - "3001:3001" diff --git a/packages/web/src/app/game/manager/[gameId]/page.tsx b/packages/web/src/app/game/manager/[gameId]/page.tsx index b00d291..24bcddd 100644 --- a/packages/web/src/app/game/manager/[gameId]/page.tsx +++ b/packages/web/src/app/game/manager/[gameId]/page.tsx @@ -40,7 +40,6 @@ export default function ManagerGame() { useEvent( "manager:successReconnect", ({ gameId, status, players, currentQuestion }) => { - console.log("manager:successReconnect", gameId) setGameId(gameId) setStatus(status.name, status.data) setPlayers(players) diff --git a/packages/web/src/components/game/states/Podium.tsx b/packages/web/src/components/game/states/Podium.tsx index 7e4ed7c..8934713 100644 --- a/packages/web/src/components/game/states/Podium.tsx +++ b/packages/web/src/components/game/states/Podium.tsx @@ -39,8 +39,6 @@ export default function Podium({ data: { subject, top } }: Props) { }) useEffect(() => { - console.log(apparition) - switch (apparition) { case 4: sfxRoolStop() From ac486b3d7d0a755ab1d8cae190b4f23b2a81f974 Mon Sep 17 00:00:00 2001 From: Ralex <95540504+Ralex91@users.noreply.github.com> Date: Sat, 25 Oct 2025 13:43:09 +0200 Subject: [PATCH 06/17] chore(packages): update --- packages/common/package.json | 4 +- packages/socket/package.json | 10 +- packages/web/package.json | 10 +- pnpm-lock.yaml | 1112 ++++++++++++++-------------------- 4 files changed, 453 insertions(+), 683 deletions(-) diff --git a/packages/common/package.json b/packages/common/package.json index f9f4b6f..ff3a73e 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -11,10 +11,10 @@ }, "devDependencies": { "@eslint/js": "^9.38.0", - "@types/node": "^20.19.22", + "@types/node": "^20.19.23", "eslint": "^9.38.0", "globals": "^16.4.0", "typescript": "^5.9.3", - "typescript-eslint": "^8.46.1" + "typescript-eslint": "^8.46.2" } } diff --git a/packages/socket/package.json b/packages/socket/package.json index 8edcf74..299ff9d 100644 --- a/packages/socket/package.json +++ b/packages/socket/package.json @@ -17,15 +17,15 @@ "dayjs": "^1.11.18", "socket.io": "^4.8.1", "uuid": "^13.0.0", - "zod": "^4.1.11" + "zod": "^4.1.12" }, "devDependencies": { "@eslint/js": "^9.38.0", - "@types/node": "^24.8.1", - "esbuild": "^0.25.10", - "eslint": "^9", + "@types/node": "^24.9.1", + "esbuild": "^0.25.11", + "eslint": "^9.38.0", "globals": "^16.4.0", "tsx": "^4.20.6", - "typescript-eslint": "^8.46.1" + "typescript-eslint": "^8.46.2" } } diff --git a/packages/web/package.json b/packages/web/package.json index 5f9c43b..6e5f41d 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -12,7 +12,7 @@ "@rahoot/socket": "workspace:*", "@t3-oss/env-nextjs": "^0.13.8", "clsx": "^2.1.1", - "ky": "^1.12.0", + "ky": "^1.13.0", "next": "15.5.4", "react": "19.1.0", "react-confetti": "^6.4.0", @@ -27,8 +27,8 @@ }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", - "@tailwindcss/postcss": "^4.1.14", - "@types/node": "^20.19.22", + "@tailwindcss/postcss": "^4.1.16", + "@types/node": "^20.19.23", "@types/react": "^19.2.2", "@types/react-dom": "^19.2.2", "eslint": "^9.38.0", @@ -38,8 +38,8 @@ "globals": "^16.4.0", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.6.14", - "tailwindcss": "^4.1.14", + "tailwindcss": "^4.1.16", "typescript": "^5.9.3", - "typescript-eslint": "^8.46.1" + "typescript-eslint": "^8.46.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 51b12c8..a13227c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,8 +28,8 @@ importers: specifier: ^9.38.0 version: 9.38.0 '@types/node': - specifier: ^20.19.22 - version: 20.19.22 + specifier: ^20.19.23 + version: 20.19.23 eslint: specifier: ^9.38.0 version: 9.38.0(jiti@2.6.1) @@ -40,8 +40,8 @@ importers: specifier: ^5.9.3 version: 5.9.3 typescript-eslint: - specifier: ^8.46.1 - version: 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + specifier: ^8.46.2 + version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) packages/socket: dependencies: @@ -50,7 +50,7 @@ importers: version: link:../common '@t3-oss/env-core': specifier: ^0.13.8 - version: 0.13.8(typescript@5.9.3)(zod@4.1.11) + version: 0.13.8(typescript@5.9.3)(zod@4.1.12) dayjs: specifier: ^1.11.18 version: 1.11.18 @@ -61,21 +61,21 @@ importers: specifier: ^13.0.0 version: 13.0.0 zod: - specifier: ^4.1.11 - version: 4.1.11 + specifier: ^4.1.12 + version: 4.1.12 devDependencies: '@eslint/js': specifier: ^9.38.0 version: 9.38.0 '@types/node': - specifier: ^24.8.1 - version: 24.8.1 + specifier: ^24.9.1 + version: 24.9.1 esbuild: - specifier: ^0.25.10 - version: 0.25.10 + specifier: ^0.25.11 + version: 0.25.11 eslint: - specifier: ^9 - version: 9.36.0(jiti@2.6.1) + specifier: ^9.38.0 + version: 9.38.0(jiti@2.6.1) globals: specifier: ^16.4.0 version: 16.4.0 @@ -83,8 +83,8 @@ importers: specifier: ^4.20.6 version: 4.20.6 typescript-eslint: - specifier: ^8.46.1 - version: 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + specifier: ^8.46.2 + version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) packages/web: dependencies: @@ -101,11 +101,11 @@ importers: specifier: ^2.1.1 version: 2.1.1 ky: - specifier: ^1.12.0 - version: 1.12.0 + specifier: ^1.13.0 + version: 1.13.0 next: specifier: 15.5.4 - version: 15.5.4(@babel/core@7.28.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 15.5.4(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: specifier: 19.1.0 version: 19.1.0 @@ -141,11 +141,11 @@ importers: specifier: ^3.3.1 version: 3.3.1 '@tailwindcss/postcss': - specifier: ^4.1.14 - version: 4.1.14 + specifier: ^4.1.16 + version: 4.1.16 '@types/node': - specifier: ^20.19.22 - version: 20.19.22 + specifier: ^20.19.23 + version: 20.19.23 '@types/react': specifier: ^19.2.2 version: 19.2.2 @@ -174,14 +174,14 @@ importers: specifier: ^0.6.14 version: 0.6.14(prettier@3.6.2) tailwindcss: - specifier: ^4.1.14 - version: 4.1.14 + specifier: ^4.1.16 + version: 4.1.16 typescript: specifier: ^5.9.3 version: 5.9.3 typescript-eslint: - specifier: ^8.46.1 - version: 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + specifier: ^8.46.2 + version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) packages: @@ -193,16 +193,16 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.4': - resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.4': - resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.3': - resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.27.2': @@ -227,8 +227,8 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} '@babel/helper-validator-option@7.27.1': @@ -239,8 +239,8 @@ packages: resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.4': - resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -248,175 +248,175 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.4': - resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.4': - resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - '@emnapi/core@1.5.0': - resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==} + '@emnapi/core@1.6.0': + resolution: {integrity: sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg==} - '@emnapi/runtime@1.5.0': - resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==} + '@emnapi/runtime@1.6.0': + resolution: {integrity: sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==} '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} - '@esbuild/aix-ppc64@0.25.10': - resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} + '@esbuild/aix-ppc64@0.25.11': + resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.10': - resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} + '@esbuild/android-arm64@0.25.11': + resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.10': - resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} + '@esbuild/android-arm@0.25.11': + resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.10': - resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} + '@esbuild/android-x64@0.25.11': + resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.10': - resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} + '@esbuild/darwin-arm64@0.25.11': + resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.10': - resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} + '@esbuild/darwin-x64@0.25.11': + resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.10': - resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} + '@esbuild/freebsd-arm64@0.25.11': + resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.10': - resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} + '@esbuild/freebsd-x64@0.25.11': + resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.10': - resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} + '@esbuild/linux-arm64@0.25.11': + resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.10': - resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} + '@esbuild/linux-arm@0.25.11': + resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.10': - resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} + '@esbuild/linux-ia32@0.25.11': + resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.10': - resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} + '@esbuild/linux-loong64@0.25.11': + resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.10': - resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} + '@esbuild/linux-mips64el@0.25.11': + resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.10': - resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} + '@esbuild/linux-ppc64@0.25.11': + resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.10': - resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} + '@esbuild/linux-riscv64@0.25.11': + resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.10': - resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} + '@esbuild/linux-s390x@0.25.11': + resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.10': - resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} + '@esbuild/linux-x64@0.25.11': + resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.10': - resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} + '@esbuild/netbsd-arm64@0.25.11': + resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.10': - resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} + '@esbuild/netbsd-x64@0.25.11': + resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.10': - resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} + '@esbuild/openbsd-arm64@0.25.11': + resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.10': - resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} + '@esbuild/openbsd-x64@0.25.11': + resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.10': - resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} + '@esbuild/openharmony-arm64@0.25.11': + resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.10': - resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} + '@esbuild/sunos-x64@0.25.11': + resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.10': - resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} + '@esbuild/win32-arm64@0.25.11': + resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.10': - resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} + '@esbuild/win32-ia32@0.25.11': + resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.10': - resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} + '@esbuild/win32-x64@0.25.11': + resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -427,30 +427,18 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.21.0': - resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-array@0.21.1': resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.3.1': - resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.4.1': resolution: {integrity: sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.15.2': - resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.16.0': resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -459,26 +447,14 @@ packages: resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.36.0': - resolution: {integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.38.0': resolution: {integrity: sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.6': - resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.7': resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.3.5': - resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.4.0': resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -625,10 +601,6 @@ packages: cpu: [x64] os: [win32] - '@isaacs/fs-minipass@4.0.1': - resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} - engines: {node: '>=18.0.0'} - '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -721,8 +693,8 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@rushstack/eslint-patch@1.14.0': - resolution: {integrity: sha512-WJFej426qe4RWOm9MMtP4V3CV4AucXolQty+GRgAWLgQXmpCuwzs7hEpxxhSc/znXUSxum9d/P/32MW0FlAAlA==} + '@rushstack/eslint-patch@1.14.1': + resolution: {integrity: sha512-jGTk8UD/RdjsNZW8qq10r0RBvxL8OWtoT+kImlzPDFilmozzM+9QmIJsmze9UiSBrFU45ZxhTYBypn9q9z/VfQ==} '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} @@ -764,65 +736,65 @@ packages: zod: optional: true - '@tailwindcss/node@4.1.14': - resolution: {integrity: sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==} + '@tailwindcss/node@4.1.16': + resolution: {integrity: sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==} - '@tailwindcss/oxide-android-arm64@4.1.14': - resolution: {integrity: sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==} + '@tailwindcss/oxide-android-arm64@4.1.16': + resolution: {integrity: sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.1.14': - resolution: {integrity: sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==} + '@tailwindcss/oxide-darwin-arm64@4.1.16': + resolution: {integrity: sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.1.14': - resolution: {integrity: sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==} + '@tailwindcss/oxide-darwin-x64@4.1.16': + resolution: {integrity: sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.1.14': - resolution: {integrity: sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==} + '@tailwindcss/oxide-freebsd-x64@4.1.16': + resolution: {integrity: sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14': - resolution: {integrity: sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16': + resolution: {integrity: sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.1.14': - resolution: {integrity: sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==} + '@tailwindcss/oxide-linux-arm64-gnu@4.1.16': + resolution: {integrity: sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.1.14': - resolution: {integrity: sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==} + '@tailwindcss/oxide-linux-arm64-musl@4.1.16': + resolution: {integrity: sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.1.14': - resolution: {integrity: sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==} + '@tailwindcss/oxide-linux-x64-gnu@4.1.16': + resolution: {integrity: sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.1.14': - resolution: {integrity: sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==} + '@tailwindcss/oxide-linux-x64-musl@4.1.16': + resolution: {integrity: sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-wasm32-wasi@4.1.14': - resolution: {integrity: sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==} + '@tailwindcss/oxide-wasm32-wasi@4.1.16': + resolution: {integrity: sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -833,24 +805,24 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.1.14': - resolution: {integrity: sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==} + '@tailwindcss/oxide-win32-arm64-msvc@4.1.16': + resolution: {integrity: sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.1.14': - resolution: {integrity: sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==} + '@tailwindcss/oxide-win32-x64-msvc@4.1.16': + resolution: {integrity: sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.1.14': - resolution: {integrity: sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==} + '@tailwindcss/oxide@4.1.16': + resolution: {integrity: sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg==} engines: {node: '>= 10'} - '@tailwindcss/postcss@4.1.14': - resolution: {integrity: sha512-BdMjIxy7HUNThK87C7BC8I1rE8BVUsfNQSI5siQ4JK3iIa3w0XyVvVL9SXLWO//CtYTcp1v7zci0fYwJOjB+Zg==} + '@tailwindcss/postcss@4.1.16': + resolution: {integrity: sha512-Qn3SFGPXYQMKR/UtqS+dqvPrzEeBZHrFA92maT4zijCVggdsXnDBMsPFJo1eArX3J+O+Gi+8pV4PkqjLCNBk3A==} '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -867,11 +839,11 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/node@20.19.22': - resolution: {integrity: sha512-hRnu+5qggKDSyWHlnmThnUqg62l29Aj/6vcYgUaSFL9oc7DVjeWEQN3PRgdSc6F8d9QRMWkf36CLMch1Do/+RQ==} + '@types/node@20.19.23': + resolution: {integrity: sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ==} - '@types/node@24.8.1': - resolution: {integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==} + '@types/node@24.9.1': + resolution: {integrity: sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==} '@types/react-dom@19.2.2': resolution: {integrity: sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==} @@ -881,63 +853,63 @@ packages: '@types/react@19.2.2': resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==} - '@typescript-eslint/eslint-plugin@8.46.1': - resolution: {integrity: sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==} + '@typescript-eslint/eslint-plugin@8.46.2': + resolution: {integrity: sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.46.1 + '@typescript-eslint/parser': ^8.46.2 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.46.1': - resolution: {integrity: sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==} + '@typescript-eslint/parser@8.46.2': + resolution: {integrity: sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.46.1': - resolution: {integrity: sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==} + '@typescript-eslint/project-service@8.46.2': + resolution: {integrity: sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.46.1': - resolution: {integrity: sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==} + '@typescript-eslint/scope-manager@8.46.2': + resolution: {integrity: sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.46.1': - resolution: {integrity: sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==} + '@typescript-eslint/tsconfig-utils@8.46.2': + resolution: {integrity: sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.46.1': - resolution: {integrity: sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==} + '@typescript-eslint/type-utils@8.46.2': + resolution: {integrity: sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.46.1': - resolution: {integrity: sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==} + '@typescript-eslint/types@8.46.2': + resolution: {integrity: sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.46.1': - resolution: {integrity: sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==} + '@typescript-eslint/typescript-estree@8.46.2': + resolution: {integrity: sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.46.1': - resolution: {integrity: sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==} + '@typescript-eslint/utils@8.46.2': + resolution: {integrity: sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.46.1': - resolution: {integrity: sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==} + '@typescript-eslint/visitor-keys@8.46.2': + resolution: {integrity: sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -1121,8 +1093,8 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - baseline-browser-mapping@2.8.18: - resolution: {integrity: sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w==} + baseline-browser-mapping@2.8.20: + resolution: {integrity: sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ==} hasBin: true brace-expansion@1.1.12: @@ -1135,8 +1107,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.26.3: - resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} + browserslist@4.27.0: + resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1163,10 +1135,6 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chownr@3.0.0: - resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} - engines: {node: '>=18'} - client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} @@ -1285,8 +1253,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.237: - resolution: {integrity: sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==} + electron-to-chromium@1.5.240: + resolution: {integrity: sha512-OBwbZjWgrCOH+g6uJsA2/7Twpas2OlepS9uvByJjR2datRDuKGYeD+nP8lBBks2qnB7bGJNHDUx7c/YLaT3QMQ==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} @@ -1338,8 +1306,8 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - esbuild@0.25.10: - resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} + esbuild@0.25.11: + resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} engines: {node: '>=18'} hasBin: true @@ -1443,16 +1411,6 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.36.0: - resolution: {integrity: sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - eslint@9.38.0: resolution: {integrity: sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1570,11 +1528,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.10.1: - resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} - - get-tsconfig@4.12.0: - resolution: {integrity: sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw==} + get-tsconfig@4.13.0: + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -1815,8 +1770,8 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - ky@1.12.0: - resolution: {integrity: sha512-YRLmSUHCwOJRBMArtqMRLOmO7fewn3yOoui6aB8ERkRVXupa0UiaQaKbIXteMt4jUElhbdqTMsLFHs8APxxUoQ==} + ky@1.13.0: + resolution: {integrity: sha512-JeNNGs44hVUp2XxO3FY9WV28ymG7LgO4wju4HL/dCq1A8eKDcFgVrdCn1ssn+3Q/5OQilv5aYsL0DMt5mmAV9w==} engines: {node: '>=18'} language-subtag-registry@0.3.23: @@ -1830,68 +1785,74 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lightningcss-darwin-arm64@1.30.1: - resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} + lightningcss-android-arm64@1.30.2: + resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.30.2: + resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.30.1: - resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} + lightningcss-darwin-x64@1.30.2: + resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.30.1: - resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} + lightningcss-freebsd-x64@1.30.2: + resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.30.1: - resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} + lightningcss-linux-arm-gnueabihf@1.30.2: + resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.30.1: - resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} + lightningcss-linux-arm64-gnu@1.30.2: + resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - lightningcss-linux-arm64-musl@1.30.1: - resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} + lightningcss-linux-arm64-musl@1.30.2: + resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - lightningcss-linux-x64-gnu@1.30.1: - resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} + lightningcss-linux-x64-gnu@1.30.2: + resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - lightningcss-linux-x64-musl@1.30.1: - resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} + lightningcss-linux-x64-musl@1.30.2: + resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - lightningcss-win32-arm64-msvc@1.30.1: - resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} + lightningcss-win32-arm64-msvc@1.30.2: + resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.30.1: - resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} + lightningcss-win32-x64-msvc@1.30.2: + resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.30.1: - resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} + lightningcss@1.30.2: + resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} locate-path@6.0.0: @@ -1908,8 +1869,8 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - magic-string@0.30.19: - resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} @@ -1941,14 +1902,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - minizlib@3.1.0: - resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} - engines: {node: '>= 18'} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1990,8 +1943,8 @@ packages: sass: optional: true - node-releases@2.0.25: - resolution: {integrity: sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==} + node-releases@2.0.26: + resolution: {integrity: sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -2202,8 +2155,8 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} hasBin: true @@ -2237,11 +2190,6 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} - engines: {node: '>=10'} - hasBin: true - semver@7.7.3: resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} @@ -2365,17 +2313,13 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tailwindcss@4.1.14: - resolution: {integrity: sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==} + tailwindcss@4.1.16: + resolution: {integrity: sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==} tapable@2.3.0: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} - tar@7.5.1: - resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==} - engines: {node: '>=18'} - tiny-case@1.0.3: resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} @@ -2434,8 +2378,8 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typescript-eslint@8.46.1: - resolution: {integrity: sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==} + typescript-eslint@8.46.2: + resolution: {integrity: sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -2453,14 +2397,14 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.14.0: - resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -2525,10 +2469,6 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yallist@5.0.0: - resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} - engines: {node: '>=18'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -2545,9 +2485,6 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.1.11: - resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} - zod@4.1.12: resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==} @@ -2575,23 +2512,23 @@ snapshots: '@babel/code-frame@7.27.1': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.4': {} + '@babel/compat-data@7.28.5': {} - '@babel/core@7.28.4': + '@babel/core@7.28.5': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -2601,19 +2538,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.28.3': + '@babel/generator@7.28.5': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.28.4 + '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.26.3 + browserslist: 4.27.0 lru-cache: 5.1.1 semver: 6.3.1 @@ -2621,65 +2558,65 @@ snapshots: '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.5 '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.4 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-option@7.27.1': {} '@babel/helpers@7.28.4': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 - '@babel/parser@7.28.4': + '@babel/parser@7.28.5': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 - '@babel/traverse@7.28.4': + '@babel/traverse@7.28.5': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.28.4': + '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 - '@emnapi/core@1.5.0': + '@emnapi/core@1.6.0': dependencies: '@emnapi/wasi-threads': 1.1.0 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.5.0': + '@emnapi/runtime@1.6.0': dependencies: tslib: 2.8.1 optional: true @@ -2689,103 +2626,90 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.25.10': + '@esbuild/aix-ppc64@0.25.11': optional: true - '@esbuild/android-arm64@0.25.10': + '@esbuild/android-arm64@0.25.11': optional: true - '@esbuild/android-arm@0.25.10': + '@esbuild/android-arm@0.25.11': optional: true - '@esbuild/android-x64@0.25.10': + '@esbuild/android-x64@0.25.11': optional: true - '@esbuild/darwin-arm64@0.25.10': + '@esbuild/darwin-arm64@0.25.11': optional: true - '@esbuild/darwin-x64@0.25.10': + '@esbuild/darwin-x64@0.25.11': optional: true - '@esbuild/freebsd-arm64@0.25.10': + '@esbuild/freebsd-arm64@0.25.11': optional: true - '@esbuild/freebsd-x64@0.25.10': + '@esbuild/freebsd-x64@0.25.11': optional: true - '@esbuild/linux-arm64@0.25.10': + '@esbuild/linux-arm64@0.25.11': optional: true - '@esbuild/linux-arm@0.25.10': + '@esbuild/linux-arm@0.25.11': optional: true - '@esbuild/linux-ia32@0.25.10': + '@esbuild/linux-ia32@0.25.11': optional: true - '@esbuild/linux-loong64@0.25.10': + '@esbuild/linux-loong64@0.25.11': optional: true - '@esbuild/linux-mips64el@0.25.10': + '@esbuild/linux-mips64el@0.25.11': optional: true - '@esbuild/linux-ppc64@0.25.10': + '@esbuild/linux-ppc64@0.25.11': optional: true - '@esbuild/linux-riscv64@0.25.10': + '@esbuild/linux-riscv64@0.25.11': optional: true - '@esbuild/linux-s390x@0.25.10': + '@esbuild/linux-s390x@0.25.11': optional: true - '@esbuild/linux-x64@0.25.10': + '@esbuild/linux-x64@0.25.11': optional: true - '@esbuild/netbsd-arm64@0.25.10': + '@esbuild/netbsd-arm64@0.25.11': optional: true - '@esbuild/netbsd-x64@0.25.10': + '@esbuild/netbsd-x64@0.25.11': optional: true - '@esbuild/openbsd-arm64@0.25.10': + '@esbuild/openbsd-arm64@0.25.11': optional: true - '@esbuild/openbsd-x64@0.25.10': + '@esbuild/openbsd-x64@0.25.11': optional: true - '@esbuild/openharmony-arm64@0.25.10': + '@esbuild/openharmony-arm64@0.25.11': optional: true - '@esbuild/sunos-x64@0.25.10': + '@esbuild/sunos-x64@0.25.11': optional: true - '@esbuild/win32-arm64@0.25.10': + '@esbuild/win32-arm64@0.25.11': optional: true - '@esbuild/win32-ia32@0.25.10': + '@esbuild/win32-ia32@0.25.11': optional: true - '@esbuild/win32-x64@0.25.10': + '@esbuild/win32-x64@0.25.11': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.1))': - dependencies: - eslint: 9.36.0(jiti@2.6.1) - eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.9.0(eslint@9.38.0(jiti@2.6.1))': dependencies: eslint: 9.38.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.1': {} - - '@eslint/config-array@0.21.0': - dependencies: - '@eslint/object-schema': 2.1.6 - debug: 4.4.3 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color + '@eslint-community/regexpp@4.12.2': {} '@eslint/config-array@0.21.1': dependencies: @@ -2795,16 +2719,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.3.1': {} - '@eslint/config-helpers@0.4.1': dependencies: '@eslint/core': 0.16.0 - '@eslint/core@0.15.2': - dependencies: - '@types/json-schema': 7.0.15 - '@eslint/core@0.16.0': dependencies: '@types/json-schema': 7.0.15 @@ -2823,19 +2741,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.36.0': {} - '@eslint/js@9.38.0': {} - '@eslint/object-schema@2.1.6': {} - '@eslint/object-schema@2.1.7': {} - '@eslint/plugin-kit@0.3.5': - dependencies: - '@eslint/core': 0.15.2 - levn: 0.4.1 - '@eslint/plugin-kit@0.4.0': dependencies: '@eslint/core': 0.16.0 @@ -2929,7 +2838,7 @@ snapshots: '@img/sharp-wasm32@0.34.4': dependencies: - '@emnapi/runtime': 1.5.0 + '@emnapi/runtime': 1.6.0 optional: true '@img/sharp-win32-arm64@0.34.4': @@ -2941,10 +2850,6 @@ snapshots: '@img/sharp-win32-x64@0.34.4': optional: true - '@isaacs/fs-minipass@4.0.1': - dependencies: - minipass: 7.1.2 - '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2966,8 +2871,8 @@ snapshots: '@napi-rs/wasm-runtime@0.2.12': dependencies: - '@emnapi/core': 1.5.0 - '@emnapi/runtime': 1.5.0 + '@emnapi/core': 1.6.0 + '@emnapi/runtime': 1.6.0 '@tybys/wasm-util': 0.10.1 optional: true @@ -3017,7 +2922,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/eslint-patch@1.14.0': {} + '@rushstack/eslint-patch@1.14.1': {} '@socket.io/component-emitter@3.1.2': {} @@ -3025,11 +2930,6 @@ snapshots: dependencies: tslib: 2.8.1 - '@t3-oss/env-core@0.13.8(typescript@5.9.3)(zod@4.1.11)': - optionalDependencies: - typescript: 5.9.3 - zod: 4.1.11 - '@t3-oss/env-core@0.13.8(typescript@5.9.3)(zod@4.1.12)': optionalDependencies: typescript: 5.9.3 @@ -3042,77 +2942,74 @@ snapshots: typescript: 5.9.3 zod: 4.1.12 - '@tailwindcss/node@4.1.14': + '@tailwindcss/node@4.1.16': dependencies: '@jridgewell/remapping': 2.3.5 enhanced-resolve: 5.18.3 jiti: 2.6.1 - lightningcss: 1.30.1 - magic-string: 0.30.19 + lightningcss: 1.30.2 + magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.1.14 + tailwindcss: 4.1.16 - '@tailwindcss/oxide-android-arm64@4.1.14': + '@tailwindcss/oxide-android-arm64@4.1.16': optional: true - '@tailwindcss/oxide-darwin-arm64@4.1.14': + '@tailwindcss/oxide-darwin-arm64@4.1.16': optional: true - '@tailwindcss/oxide-darwin-x64@4.1.14': + '@tailwindcss/oxide-darwin-x64@4.1.16': optional: true - '@tailwindcss/oxide-freebsd-x64@4.1.14': + '@tailwindcss/oxide-freebsd-x64@4.1.16': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.1.14': + '@tailwindcss/oxide-linux-arm64-gnu@4.1.16': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.1.14': + '@tailwindcss/oxide-linux-arm64-musl@4.1.16': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.1.14': + '@tailwindcss/oxide-linux-x64-gnu@4.1.16': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.1.14': + '@tailwindcss/oxide-linux-x64-musl@4.1.16': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.1.14': + '@tailwindcss/oxide-wasm32-wasi@4.1.16': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.1.14': + '@tailwindcss/oxide-win32-arm64-msvc@4.1.16': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.1.14': + '@tailwindcss/oxide-win32-x64-msvc@4.1.16': optional: true - '@tailwindcss/oxide@4.1.14': - dependencies: - detect-libc: 2.1.2 - tar: 7.5.1 + '@tailwindcss/oxide@4.1.16': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.14 - '@tailwindcss/oxide-darwin-arm64': 4.1.14 - '@tailwindcss/oxide-darwin-x64': 4.1.14 - '@tailwindcss/oxide-freebsd-x64': 4.1.14 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.14 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.14 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.14 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.14 - '@tailwindcss/oxide-linux-x64-musl': 4.1.14 - '@tailwindcss/oxide-wasm32-wasi': 4.1.14 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.14 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.14 + '@tailwindcss/oxide-android-arm64': 4.1.16 + '@tailwindcss/oxide-darwin-arm64': 4.1.16 + '@tailwindcss/oxide-darwin-x64': 4.1.16 + '@tailwindcss/oxide-freebsd-x64': 4.1.16 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.16 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.16 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.16 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.16 + '@tailwindcss/oxide-linux-x64-musl': 4.1.16 + '@tailwindcss/oxide-wasm32-wasi': 4.1.16 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.16 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.16 - '@tailwindcss/postcss@4.1.14': + '@tailwindcss/postcss@4.1.16': dependencies: '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.1.14 - '@tailwindcss/oxide': 4.1.14 + '@tailwindcss/node': 4.1.16 + '@tailwindcss/oxide': 4.1.16 postcss: 8.5.6 - tailwindcss: 4.1.14 + tailwindcss: 4.1.16 '@tybys/wasm-util@0.10.1': dependencies: @@ -3121,7 +3018,7 @@ snapshots: '@types/cors@2.8.19': dependencies: - '@types/node': 20.19.22 + '@types/node': 20.19.23 '@types/estree@1.0.8': {} @@ -3129,13 +3026,13 @@ snapshots: '@types/json5@0.0.29': {} - '@types/node@20.19.22': + '@types/node@20.19.23': dependencies: undici-types: 6.21.0 - '@types/node@24.8.1': + '@types/node@24.9.1': dependencies: - undici-types: 7.14.0 + undici-types: 7.16.0 '@types/react-dom@19.2.2(@types/react@19.2.2)': dependencies: @@ -3145,31 +3042,14 @@ snapshots: dependencies: csstype: 3.1.3 - '@typescript-eslint/eslint-plugin@8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.46.1 - '@typescript-eslint/type-utils': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.1 - eslint: 9.36.0(jiti@2.6.1) - graphemer: 1.4.0 - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/eslint-plugin@8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.46.1 - '@typescript-eslint/type-utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.1 + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.2 + '@typescript-eslint/type-utils': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.2 eslint: 9.38.0(jiti@2.6.1) graphemer: 1.4.0 ignore: 7.0.5 @@ -3179,65 +3059,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.46.1 - '@typescript-eslint/types': 8.46.1 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.1 - debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.46.1 - '@typescript-eslint/types': 8.46.1 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.1 + '@typescript-eslint/scope-manager': 8.46.2 + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.2 debug: 4.4.3 eslint: 9.38.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.46.1(typescript@5.9.3)': + '@typescript-eslint/project-service@8.46.2(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3) - '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.9.3) + '@typescript-eslint/types': 8.46.2 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.46.1': + '@typescript-eslint/scope-manager@8.46.2': dependencies: - '@typescript-eslint/types': 8.46.1 - '@typescript-eslint/visitor-keys': 8.46.1 + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/visitor-keys': 8.46.2 - '@typescript-eslint/tsconfig-utils@8.46.1(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.46.2(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.46.1 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.1) - ts-api-utils: 2.1.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/type-utils@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/types': 8.46.1 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3 eslint: 9.38.0(jiti@2.6.1) ts-api-utils: 2.1.0(typescript@5.9.3) @@ -3245,49 +3101,38 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.46.1': {} + '@typescript-eslint/types@8.46.2': {} - '@typescript-eslint/typescript-estree@8.46.1(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.46.2(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.46.1(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3) - '@typescript-eslint/types': 8.46.1 - '@typescript-eslint/visitor-keys': 8.46.1 + '@typescript-eslint/project-service': 8.46.2(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.9.3) + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/visitor-keys': 8.46.2 debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.7.2 + semver: 7.7.3 ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.46.1 - '@typescript-eslint/types': 8.46.1 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) - eslint: 9.36.0(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.46.1 - '@typescript-eslint/types': 8.46.1 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.2 + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3) eslint: 9.38.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.46.1': + '@typescript-eslint/visitor-keys@8.46.2': dependencies: - '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/types': 8.46.2 eslint-visitor-keys: 4.2.1 '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -3458,7 +3303,7 @@ snapshots: base64id@2.0.0: {} - baseline-browser-mapping@2.8.18: {} + baseline-browser-mapping@2.8.20: {} brace-expansion@1.1.12: dependencies: @@ -3473,13 +3318,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.26.3: + browserslist@4.27.0: dependencies: - baseline-browser-mapping: 2.8.18 + baseline-browser-mapping: 2.8.20 caniuse-lite: 1.0.30001751 - electron-to-chromium: 1.5.237 - node-releases: 2.0.25 - update-browserslist-db: 1.1.3(browserslist@4.26.3) + electron-to-chromium: 1.5.240 + node-releases: 2.0.26 + update-browserslist-db: 1.1.4(browserslist@4.27.0) call-bind-apply-helpers@1.0.2: dependencies: @@ -3507,8 +3352,6 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chownr@3.0.0: {} - client-only@0.0.1: {} clsx@2.1.1: {} @@ -3613,7 +3456,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.237: {} + electron-to-chromium@1.5.240: {} emoji-regex@9.2.2: {} @@ -3634,7 +3477,7 @@ snapshots: engine.io@6.6.4: dependencies: '@types/cors': 2.8.19 - '@types/node': 20.19.22 + '@types/node': 20.19.23 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -3753,34 +3596,34 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild@0.25.10: + esbuild@0.25.11: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.10 - '@esbuild/android-arm': 0.25.10 - '@esbuild/android-arm64': 0.25.10 - '@esbuild/android-x64': 0.25.10 - '@esbuild/darwin-arm64': 0.25.10 - '@esbuild/darwin-x64': 0.25.10 - '@esbuild/freebsd-arm64': 0.25.10 - '@esbuild/freebsd-x64': 0.25.10 - '@esbuild/linux-arm': 0.25.10 - '@esbuild/linux-arm64': 0.25.10 - '@esbuild/linux-ia32': 0.25.10 - '@esbuild/linux-loong64': 0.25.10 - '@esbuild/linux-mips64el': 0.25.10 - '@esbuild/linux-ppc64': 0.25.10 - '@esbuild/linux-riscv64': 0.25.10 - '@esbuild/linux-s390x': 0.25.10 - '@esbuild/linux-x64': 0.25.10 - '@esbuild/netbsd-arm64': 0.25.10 - '@esbuild/netbsd-x64': 0.25.10 - '@esbuild/openbsd-arm64': 0.25.10 - '@esbuild/openbsd-x64': 0.25.10 - '@esbuild/openharmony-arm64': 0.25.10 - '@esbuild/sunos-x64': 0.25.10 - '@esbuild/win32-arm64': 0.25.10 - '@esbuild/win32-ia32': 0.25.10 - '@esbuild/win32-x64': 0.25.10 + '@esbuild/aix-ppc64': 0.25.11 + '@esbuild/android-arm': 0.25.11 + '@esbuild/android-arm64': 0.25.11 + '@esbuild/android-x64': 0.25.11 + '@esbuild/darwin-arm64': 0.25.11 + '@esbuild/darwin-x64': 0.25.11 + '@esbuild/freebsd-arm64': 0.25.11 + '@esbuild/freebsd-x64': 0.25.11 + '@esbuild/linux-arm': 0.25.11 + '@esbuild/linux-arm64': 0.25.11 + '@esbuild/linux-ia32': 0.25.11 + '@esbuild/linux-loong64': 0.25.11 + '@esbuild/linux-mips64el': 0.25.11 + '@esbuild/linux-ppc64': 0.25.11 + '@esbuild/linux-riscv64': 0.25.11 + '@esbuild/linux-s390x': 0.25.11 + '@esbuild/linux-x64': 0.25.11 + '@esbuild/netbsd-arm64': 0.25.11 + '@esbuild/netbsd-x64': 0.25.11 + '@esbuild/openbsd-arm64': 0.25.11 + '@esbuild/openbsd-x64': 0.25.11 + '@esbuild/openharmony-arm64': 0.25.11 + '@esbuild/sunos-x64': 0.25.11 + '@esbuild/win32-arm64': 0.25.11 + '@esbuild/win32-ia32': 0.25.11 + '@esbuild/win32-x64': 0.25.11 escalade@3.2.0: {} @@ -3789,13 +3632,13 @@ snapshots: eslint-config-next@15.5.4(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3): dependencies: '@next/eslint-plugin-next': 15.5.4 - '@rushstack/eslint-patch': 1.14.0 - '@typescript-eslint/eslint-plugin': 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@rushstack/eslint-patch': 1.14.1 + '@typescript-eslint/eslint-plugin': 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) eslint: 9.38.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@2.6.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.38.0(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.38.0(jiti@2.6.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.38.0(jiti@2.6.1)) @@ -3810,7 +3653,7 @@ snapshots: dependencies: debug: 3.2.7 is-core-module: 2.16.1 - resolve: 1.22.10 + resolve: 1.22.11 transitivePeerDependencies: - supports-color @@ -3819,28 +3662,28 @@ snapshots: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 eslint: 9.38.0(jiti@2.6.1) - get-tsconfig: 4.12.0 + get-tsconfig: 4.13.0 is-bun-module: 2.0.0 stable-hash: 0.0.5 tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) eslint: 9.38.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -3851,7 +3694,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.38.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -3863,7 +3706,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -3894,8 +3737,8 @@ snapshots: eslint-plugin-react-hooks@6.1.1(eslint@9.38.0(jiti@2.6.1)): dependencies: - '@babel/core': 7.28.4 - '@babel/parser': 7.28.4 + '@babel/core': 7.28.5 + '@babel/parser': 7.28.5 eslint: 9.38.0(jiti@2.6.1) zod: 4.1.12 zod-validation-error: 4.0.2(zod@4.1.12) @@ -3933,52 +3776,10 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.36.0(jiti@2.6.1): - dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.21.0 - '@eslint/config-helpers': 0.3.1 - '@eslint/core': 0.15.2 - '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.36.0 - '@eslint/plugin-kit': 0.3.5 - '@humanfs/node': 0.16.7 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.6.1 - transitivePeerDependencies: - - supports-color - eslint@9.38.0(jiti@2.6.1): dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.1 + '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.1 '@eslint/core': 0.16.0 @@ -4132,11 +3933,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.10.1: - dependencies: - resolve-pkg-maps: 1.0.0 - - get-tsconfig@4.12.0: + get-tsconfig@4.13.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -4366,7 +4163,7 @@ snapshots: dependencies: json-buffer: 3.0.1 - ky@1.12.0: {} + ky@1.13.0: {} language-subtag-registry@0.3.23: {} @@ -4379,50 +4176,54 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lightningcss-darwin-arm64@1.30.1: + lightningcss-android-arm64@1.30.2: optional: true - lightningcss-darwin-x64@1.30.1: + lightningcss-darwin-arm64@1.30.2: optional: true - lightningcss-freebsd-x64@1.30.1: + lightningcss-darwin-x64@1.30.2: optional: true - lightningcss-linux-arm-gnueabihf@1.30.1: + lightningcss-freebsd-x64@1.30.2: optional: true - lightningcss-linux-arm64-gnu@1.30.1: + lightningcss-linux-arm-gnueabihf@1.30.2: optional: true - lightningcss-linux-arm64-musl@1.30.1: + lightningcss-linux-arm64-gnu@1.30.2: optional: true - lightningcss-linux-x64-gnu@1.30.1: + lightningcss-linux-arm64-musl@1.30.2: optional: true - lightningcss-linux-x64-musl@1.30.1: + lightningcss-linux-x64-gnu@1.30.2: optional: true - lightningcss-win32-arm64-msvc@1.30.1: + lightningcss-linux-x64-musl@1.30.2: optional: true - lightningcss-win32-x64-msvc@1.30.1: + lightningcss-win32-arm64-msvc@1.30.2: optional: true - lightningcss@1.30.1: + lightningcss-win32-x64-msvc@1.30.2: + optional: true + + lightningcss@1.30.2: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-darwin-arm64: 1.30.1 - lightningcss-darwin-x64: 1.30.1 - lightningcss-freebsd-x64: 1.30.1 - lightningcss-linux-arm-gnueabihf: 1.30.1 - lightningcss-linux-arm64-gnu: 1.30.1 - lightningcss-linux-arm64-musl: 1.30.1 - lightningcss-linux-x64-gnu: 1.30.1 - lightningcss-linux-x64-musl: 1.30.1 - lightningcss-win32-arm64-msvc: 1.30.1 - lightningcss-win32-x64-msvc: 1.30.1 + lightningcss-android-arm64: 1.30.2 + lightningcss-darwin-arm64: 1.30.2 + lightningcss-darwin-x64: 1.30.2 + lightningcss-freebsd-x64: 1.30.2 + lightningcss-linux-arm-gnueabihf: 1.30.2 + lightningcss-linux-arm64-gnu: 1.30.2 + lightningcss-linux-arm64-musl: 1.30.2 + lightningcss-linux-x64-gnu: 1.30.2 + lightningcss-linux-x64-musl: 1.30.2 + lightningcss-win32-arm64-msvc: 1.30.2 + lightningcss-win32-x64-msvc: 1.30.2 locate-path@6.0.0: dependencies: @@ -4438,7 +4239,7 @@ snapshots: dependencies: yallist: 3.1.1 - magic-string@0.30.19: + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -4467,12 +4268,6 @@ snapshots: minimist@1.2.8: {} - minipass@7.1.2: {} - - minizlib@3.1.0: - dependencies: - minipass: 7.1.2 - ms@2.1.3: {} nanoid@3.3.11: {} @@ -4483,7 +4278,7 @@ snapshots: negotiator@0.6.3: {} - next@15.5.4(@babel/core@7.28.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next@15.5.4(@babel/core@7.28.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@next/env': 15.5.4 '@swc/helpers': 0.5.15 @@ -4491,7 +4286,7 @@ snapshots: postcss: 8.4.31 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - styled-jsx: 5.1.6(@babel/core@7.28.4)(react@19.1.0) + styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.1.0) optionalDependencies: '@next/swc-darwin-arm64': 15.5.4 '@next/swc-darwin-x64': 15.5.4 @@ -4506,7 +4301,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - node-releases@2.0.25: {} + node-releases@2.0.26: {} object-assign@4.1.1: {} @@ -4668,7 +4463,7 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve@1.22.10: + resolve@1.22.11: dependencies: is-core-module: 2.16.1 path-parse: 1.0.7 @@ -4709,8 +4504,6 @@ snapshots: semver@6.3.1: {} - semver@7.7.2: {} - semver@7.7.3: {} set-function-length@1.2.2: @@ -4903,12 +4696,12 @@ snapshots: strip-json-comments@3.1.1: {} - styled-jsx@5.1.6(@babel/core@7.28.4)(react@19.1.0): + styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.1.0): dependencies: client-only: 0.0.1 react: 19.1.0 optionalDependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.5 supports-color@7.2.0: dependencies: @@ -4916,18 +4709,10 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tailwindcss@4.1.14: {} + tailwindcss@4.1.16: {} tapable@2.3.0: {} - tar@7.5.1: - dependencies: - '@isaacs/fs-minipass': 4.0.1 - chownr: 3.0.0 - minipass: 7.1.2 - minizlib: 3.1.0 - yallist: 5.0.0 - tiny-case@1.0.3: {} tinyglobby@0.2.15: @@ -4956,8 +4741,8 @@ snapshots: tsx@4.20.6: dependencies: - esbuild: 0.25.10 - get-tsconfig: 4.10.1 + esbuild: 0.25.11 + get-tsconfig: 4.13.0 optionalDependencies: fsevents: 2.3.3 @@ -5002,23 +4787,12 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.1(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.36.0(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - typescript-eslint@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) eslint: 9.38.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: @@ -5035,7 +4809,7 @@ snapshots: undici-types@6.21.0: {} - undici-types@7.14.0: {} + undici-types@7.16.0: {} unrs-resolver@1.11.1: dependencies: @@ -5061,9 +4835,9 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - update-browserslist-db@1.1.3(browserslist@4.26.3): + update-browserslist-db@1.1.4(browserslist@4.27.0): dependencies: - browserslist: 4.26.3 + browserslist: 4.27.0 escalade: 3.2.0 picocolors: 1.1.1 @@ -5133,8 +4907,6 @@ snapshots: yallist@3.1.1: {} - yallist@5.0.0: {} - yocto-queue@0.1.0: {} yup@1.7.1: @@ -5150,8 +4922,6 @@ snapshots: zod@3.25.76: {} - zod@4.1.11: {} - zod@4.1.12: {} zustand@5.0.8(@types/react@19.2.2)(react@19.1.0): From dbefaa0557b67187d0cba72fe3a14d6ea77fea2f Mon Sep 17 00:00:00 2001 From: Ralex <95540504+Ralex91@users.noreply.github.com> Date: Sat, 25 Oct 2025 15:04:03 +0200 Subject: [PATCH 07/17] refactor(components): use arrow function syntax and improve consistency --- packages/web/src/app/(auth)/manager/page.tsx | 4 +- packages/web/src/app/(auth)/page.tsx | 4 +- packages/web/src/app/game/[gameId]/page.tsx | 4 +- .../src/app/game/manager/[gameId]/page.tsx | 4 +- packages/web/src/app/layout.tsx | 24 +++---- packages/web/src/components/AnswerButton.tsx | 30 ++++---- packages/web/src/components/Button.tsx | 27 +++---- packages/web/src/components/Form.tsx | 14 ++-- packages/web/src/components/Input.tsx | 28 ++++---- .../web/src/components/game/GameWrapper.tsx | 13 ++-- .../game/create/ManagerPassword.tsx | 4 +- .../components/game/create/SelectQuizz.tsx | 4 +- .../web/src/components/game/join/Room.tsx | 4 +- .../web/src/components/game/join/Username.tsx | 4 +- .../src/components/game/states/Answers.tsx | 6 +- .../components/game/states/Leaderboard.tsx | 40 +++++------ .../web/src/components/game/states/Podium.tsx | 10 +-- .../src/components/game/states/Prepared.tsx | 46 ++++++------ .../src/components/game/states/Question.tsx | 6 +- .../src/components/game/states/Responses.tsx | 33 ++------- .../web/src/components/game/states/Result.tsx | 6 +- .../web/src/components/game/states/Room.tsx | 4 +- .../web/src/components/game/states/Start.tsx | 4 +- .../web/src/components/game/states/Wait.tsx | 20 +++--- packages/web/src/components/icons/Circle.tsx | 42 +++++------ .../web/src/components/icons/CricleCheck.tsx | 70 +++++++++---------- .../web/src/components/icons/CricleXmark.tsx | 58 +++++++-------- .../web/src/components/icons/Pentagon.tsx | 70 +++++++++---------- packages/web/src/components/icons/Rhombus.tsx | 34 ++++----- packages/web/src/components/icons/Square.tsx | 24 +++---- .../web/src/components/icons/Triangle.tsx | 24 +++---- packages/web/src/utils/score.ts | 23 ++++++ 32 files changed, 351 insertions(+), 337 deletions(-) create mode 100644 packages/web/src/utils/score.ts diff --git a/packages/web/src/app/(auth)/manager/page.tsx b/packages/web/src/app/(auth)/manager/page.tsx index b7c3b05..0b77bfc 100644 --- a/packages/web/src/app/(auth)/manager/page.tsx +++ b/packages/web/src/app/(auth)/manager/page.tsx @@ -8,7 +8,7 @@ import { useManagerStore } from "@rahoot/web/stores/manager" import { useRouter } from "next/navigation" import { useState } from "react" -export default function Manager() { +const Manager = () => { const { setGameId, setStatus } = useManagerStore() const router = useRouter() const { socket } = useSocket() @@ -40,3 +40,5 @@ export default function Manager() { return } + +export default Manager diff --git a/packages/web/src/app/(auth)/page.tsx b/packages/web/src/app/(auth)/page.tsx index 546b3b8..976f754 100644 --- a/packages/web/src/app/(auth)/page.tsx +++ b/packages/web/src/app/(auth)/page.tsx @@ -7,7 +7,7 @@ import { usePlayerStore } from "@rahoot/web/stores/player" import { useEffect } from "react" import toast from "react-hot-toast" -export default function Home() { +const Home = () => { const { isConnected, connect } = useSocket() const { player } = usePlayerStore() @@ -27,3 +27,5 @@ export default function Home() { return } + +export default Home diff --git a/packages/web/src/app/game/[gameId]/page.tsx b/packages/web/src/app/game/[gameId]/page.tsx index 1ab789a..df8ed01 100644 --- a/packages/web/src/app/game/[gameId]/page.tsx +++ b/packages/web/src/app/game/[gameId]/page.tsx @@ -15,7 +15,7 @@ import { GAME_STATE_COMPONENTS } from "@rahoot/web/utils/constants" import { useParams, useRouter } from "next/navigation" import toast from "react-hot-toast" -export default function Game() { +const Game = () => { const router = useRouter() const { socket } = useSocket() const { gameId: gameIdParam }: { gameId?: string } = useParams() @@ -95,3 +95,5 @@ export default function Game() { return {component} } + +export default Game diff --git a/packages/web/src/app/game/manager/[gameId]/page.tsx b/packages/web/src/app/game/manager/[gameId]/page.tsx index 24bcddd..ab4f86e 100644 --- a/packages/web/src/app/game/manager/[gameId]/page.tsx +++ b/packages/web/src/app/game/manager/[gameId]/page.tsx @@ -17,7 +17,7 @@ import { GAME_STATE_COMPONENTS_MANAGER } from "@rahoot/web/utils/constants" import { useParams, useRouter } from "next/navigation" import toast from "react-hot-toast" -export default function ManagerGame() { +const ManagerGame = () => { const router = useRouter() const { gameId: gameIdParam }: { gameId?: string } = useParams() const { socket } = useSocket() @@ -131,3 +131,5 @@ export default function ManagerGame() { ) } + +export default ManagerGame diff --git a/packages/web/src/app/layout.tsx b/packages/web/src/app/layout.tsx index 99c9970..e61d32c 100644 --- a/packages/web/src/app/layout.tsx +++ b/packages/web/src/app/layout.tsx @@ -15,15 +15,15 @@ export const metadata: Metadata = { icons: "/icon.svg", } -export default function RootLayout({ children }: PropsWithChildren) { - return ( - - - -
{children}
- -
- - - ) -} +const RootLayout = ({ children }: PropsWithChildren) => ( + + + +
{children}
+ +
+ + +) + +export default RootLayout diff --git a/packages/web/src/components/AnswerButton.tsx b/packages/web/src/components/AnswerButton.tsx index 9706e84..7b757ab 100644 --- a/packages/web/src/components/AnswerButton.tsx +++ b/packages/web/src/components/AnswerButton.tsx @@ -6,22 +6,22 @@ type Props = PropsWithChildren & icon: ElementType } -export default function AnswerButton({ +const AnswerButton = ({ className, icon: Icon, children, ...otherProps -}: Props) { - return ( - - ) -} +}: Props) => ( + +) + +export default AnswerButton diff --git a/packages/web/src/components/Button.tsx b/packages/web/src/components/Button.tsx index 9505e7b..b6c5b56 100644 --- a/packages/web/src/components/Button.tsx +++ b/packages/web/src/components/Button.tsx @@ -2,16 +2,17 @@ import clsx from "clsx" import { ButtonHTMLAttributes, PropsWithChildren } from "react" type Props = ButtonHTMLAttributes & PropsWithChildren -export default function Button({ children, className, ...otherProps }: Props) { - return ( - - ) -} + +const Button = ({ children, className, ...otherProps }: Props) => ( + +) + +export default Button diff --git a/packages/web/src/components/Form.tsx b/packages/web/src/components/Form.tsx index bd584f6..7df80d5 100644 --- a/packages/web/src/components/Form.tsx +++ b/packages/web/src/components/Form.tsx @@ -1,9 +1,9 @@ import { PropsWithChildren } from "react" -export default function Form({ children }: PropsWithChildren) { - return ( -
- {children} -
- ) -} +const Form = ({ children }: PropsWithChildren) => ( +
+ {children} +
+) + +export default Form diff --git a/packages/web/src/components/Input.tsx b/packages/web/src/components/Input.tsx index 6b83b23..0246d9a 100644 --- a/packages/web/src/components/Input.tsx +++ b/packages/web/src/components/Input.tsx @@ -3,19 +3,15 @@ import React from "react" type Props = React.InputHTMLAttributes -export default function Input({ - className, - type = "text", - ...otherProps -}: Props) { - return ( - - ) -} +const Input = ({ className, type = "text", ...otherProps }: Props) => ( + +) + +export default Input diff --git a/packages/web/src/components/game/GameWrapper.tsx b/packages/web/src/components/game/GameWrapper.tsx index 49eb8ed..dff2b4e 100644 --- a/packages/web/src/components/game/GameWrapper.tsx +++ b/packages/web/src/components/game/GameWrapper.tsx @@ -3,13 +3,13 @@ import { Status } from "@rahoot/common/types/game/status" import background from "@rahoot/web/assets/background.webp" import Button from "@rahoot/web/components/Button" +import Loader from "@rahoot/web/components/Loader" import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider" import { usePlayerStore } from "@rahoot/web/stores/player" import { useQuestionStore } from "@rahoot/web/stores/question" import { MANAGER_SKIP_BTN } from "@rahoot/web/utils/constants" import Image from "next/image" import { PropsWithChildren } from "react" -import Loader from "../Loader" type Props = PropsWithChildren & { statusName: Status @@ -17,12 +17,7 @@ type Props = PropsWithChildren & { manager?: boolean } -export default function GameWrapper({ - children, - statusName, - onNext, - manager, -}: Props) { +const GameWrapper = ({ children, statusName, onNext, manager }: Props) => { const { isConnected } = useSocket() const { player } = usePlayerStore() const { questionStates, setQuestionStates } = useQuestionStore() @@ -61,7 +56,7 @@ export default function GameWrapper({ {manager && next && (